Esempio n. 1
0
 /**
  * @covers PhpCsFixer\Runner\Runner::fix
  * @covers PhpCsFixer\Runner\Runner::fixFile
  */
 public function testThatFixInvalidFileReportsToErrorManager()
 {
     $config = Config::create()->finder(Finder::create()->in(__DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'Fixtures' . DIRECTORY_SEPARATOR . 'FixerTest' . DIRECTORY_SEPARATOR . 'invalid'))->fixers(array(new Fixer\ClassNotation\VisibilityRequiredFixer(), new Fixer\Import\NoUnusedImportsFixer()))->setUsingCache(false);
     $errorsManager = new ErrorsManager();
     $runner = new Runner($config, new NullDiffer(), null, $errorsManager, new Linter(), true);
     $changed = $runner->fix();
     $pathToInvalidFile = 'somefile.php';
     $this->assertCount(0, $changed);
     $errors = $errorsManager->getInvalidErrors();
     $this->assertCount(1, $errors);
     $error = $errors[0];
     $this->assertInstanceOf('PhpCsFixer\\Error\\Error', $error);
     $this->assertSame(Error::TYPE_INVALID, $error->getType());
     $this->assertSame($pathToInvalidFile, $error->getFilePath());
 }
Esempio n. 2
0
 /**
  * @see Command
  */
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $verbosity = $output->getVerbosity();
     $resolver = new ConfigurationResolver();
     $resolver->setCwd(getcwd())->setDefaultConfig($this->defaultConfig)->setOptions(array('allow-risky' => $input->getOption('allow-risky'), 'config' => $input->getOption('config'), 'dry-run' => $input->getOption('dry-run'), 'rules' => $input->getOption('rules'), 'path' => $input->getArgument('path'), 'path-mode' => $input->getOption('path-mode'), 'progress' => OutputInterface::VERBOSITY_VERBOSE <= $verbosity && 'txt' === $input->getOption('format'), 'using-cache' => $input->getOption('using-cache'), 'cache-file' => $input->getOption('cache-file'), 'format' => $input->getOption('format')))->resolve();
     $reporter = ReporterFactory::create()->registerBuiltInReporters()->getReporter($resolver->getFormat());
     $stdErr = $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : ('txt' === $reporter->getFormat() ? $output : null);
     if (null !== $stdErr && extension_loaded('xdebug')) {
         $stdErr->writeln(sprintf($stdErr->isDecorated() ? '<bg=yellow;fg=black;>%s</>' : '%s', 'You are running php-cs-fixer with xdebug enabled. This has a major impact on runtime performance.'));
     }
     $config = $resolver->getConfig();
     $configFile = $resolver->getConfigFile();
     if (null !== $stdErr && $configFile) {
         $stdErr->writeln(sprintf('Loaded config from "%s".', $configFile));
     }
     $linter = new NullLinter();
     if ($config->usingLinter()) {
         try {
             $linter = new Linter($config->getPhpExecutable());
         } catch (UnavailableLinterException $e) {
             if (null !== $stdErr && $configFile) {
                 $stdErr->writeln('Unable to use linter, can not find PHP executable.');
             }
         }
     }
     if (null !== $stdErr && $config->usingCache()) {
         $cacheFile = $config->getCacheFile();
         if (is_file($cacheFile)) {
             $stdErr->writeln(sprintf('Using cache file "%s".', $cacheFile));
         }
     }
     $showProgress = $resolver->getProgress();
     $runner = new Runner($config, $input->getOption('diff') ? new SebastianBergmannDiffer() : new NullDiffer(), $showProgress ? $this->eventDispatcher : null, $this->errorsManager, $linter, $resolver->isDryRun());
     $progressOutput = $showProgress && $stdErr ? new ProcessOutput($stdErr, $this->eventDispatcher) : new NullOutput();
     $this->stopwatch->start('fixFiles');
     $changed = $runner->fix();
     $this->stopwatch->stop('fixFiles');
     $progressOutput->printLegend();
     $fixEvent = $this->stopwatch->getEvent('fixFiles');
     $reportSummary = ReportSummary::create()->setChanged($changed)->setAddAppliedFixers(OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity())->setIsDecoratedOutput($output->isDecorated())->setIsDryRun($resolver->isDryRun())->setMemory($fixEvent->getMemory())->setTime($fixEvent->getDuration());
     $output->write($reporter->generate($reportSummary));
     $invalidErrors = $this->errorsManager->getInvalidErrors();
     $exceptionErrors = $this->errorsManager->getExceptionErrors();
     $lintErrors = $this->errorsManager->getLintErrors();
     if (null !== $stdErr) {
         if (count($invalidErrors) > 0) {
             $this->listErrors($stdErr, 'linting before fixing', $invalidErrors);
         }
         if (count($exceptionErrors) > 0) {
             $this->listErrors($stdErr, 'fixing', $exceptionErrors);
         }
         if (count($lintErrors) > 0) {
             $this->listErrors($stdErr, 'linting after fixing', $lintErrors);
         }
     }
     return $this->calculateExitStatus($resolver->isDryRun(), count($changed) > 0, count($invalidErrors) > 0, count($exceptionErrors) > 0);
 }
Esempio n. 3
0
 /**
  * @see Command
  */
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $verbosity = $output->getVerbosity();
     $resolver = new ConfigurationResolver($this->defaultConfig, array('allow-risky' => $input->getOption('allow-risky'), 'config' => $input->getOption('config'), 'dry-run' => $input->getOption('dry-run'), 'rules' => $input->getOption('rules'), 'path' => $input->getArgument('path'), 'path-mode' => $input->getOption('path-mode'), 'progress' => OutputInterface::VERBOSITY_VERBOSE <= $verbosity && 'txt' === $input->getOption('format'), 'using-cache' => $input->getOption('using-cache'), 'cache-file' => $input->getOption('cache-file'), 'format' => $input->getOption('format'), 'diff' => $input->getOption('diff')), getcwd());
     $reporter = $resolver->getReporter();
     $stdErr = $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : ('txt' === $reporter->getFormat() ? $output : null);
     if (null !== $stdErr && extension_loaded('xdebug')) {
         $stdErr->writeln(sprintf($stdErr->isDecorated() ? '<bg=yellow;fg=black;>%s</>' : '%s', 'You are running php-cs-fixer with xdebug enabled. This has a major impact on runtime performance.'));
     }
     $configFile = $resolver->getConfigFile();
     if (null !== $stdErr) {
         $stdErr->writeln(sprintf('Loaded config <comment>%s</comment>%s.', $resolver->getConfig()->getName(), null === $configFile ? '' : ' from "' . $configFile . '"'));
     }
     if (null !== $stdErr && $resolver->getUsingCache()) {
         $cacheFile = $resolver->getCacheFile();
         if (is_file($cacheFile)) {
             $stdErr->writeln(sprintf('Using cache file "%s".', $cacheFile));
         }
     }
     $showProgress = $resolver->getProgress();
     $runner = new Runner($resolver->getFinder(), $resolver->getFixers(), $input->getOption('diff') ? new SebastianBergmannDiffer() : new NullDiffer(), $showProgress ? $this->eventDispatcher : null, $this->errorsManager, $resolver->getLinter(), $resolver->isDryRun(), $resolver->getCacheManager());
     $progressOutput = $showProgress && $stdErr ? new ProcessOutput($stdErr, $this->eventDispatcher) : new NullOutput();
     $this->stopwatch->start('fixFiles');
     $changed = $runner->fix();
     $this->stopwatch->stop('fixFiles');
     $progressOutput->printLegend();
     $fixEvent = $this->stopwatch->getEvent('fixFiles');
     $reportSummary = new ReportSummary($changed, $fixEvent->getDuration(), $fixEvent->getMemory(), OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity(), $resolver->isDryRun(), $output->isDecorated());
     if ($output->isDecorated()) {
         $output->write($reporter->generate($reportSummary));
     } else {
         $output->write($reporter->generate($reportSummary), false, OutputInterface::OUTPUT_RAW);
     }
     $invalidErrors = $this->errorsManager->getInvalidErrors();
     $exceptionErrors = $this->errorsManager->getExceptionErrors();
     $lintErrors = $this->errorsManager->getLintErrors();
     if (null !== $stdErr) {
         if (count($invalidErrors) > 0) {
             $this->listErrors($stdErr, 'linting before fixing', $invalidErrors);
         }
         if (count($exceptionErrors) > 0) {
             $this->listErrors($stdErr, 'fixing', $exceptionErrors);
         }
         if (count($lintErrors) > 0) {
             $this->listErrors($stdErr, 'linting after fixing', $lintErrors);
         }
     }
     return $this->calculateExitStatus($resolver->isDryRun(), count($changed) > 0, count($invalidErrors) > 0, count($exceptionErrors) > 0);
 }
 public function testThatCanReportAndRetrieveInvalidFileErrors()
 {
     $error = new Error(Error::TYPE_LINT, 'foo.php');
     $errorsManager = new ErrorsManager();
     $errorsManager->report($error);
     $this->assertFalse($errorsManager->isEmpty());
     $errors = $errorsManager->getLintErrors();
     $this->assertInternalType('array', $errors);
     $this->assertCount(1, $errors);
     $this->assertSame($error, array_shift($errors));
     $this->assertCount(0, $errorsManager->getInvalidErrors());
     $this->assertCount(0, $errorsManager->getExceptionErrors());
 }
Esempio n. 5
0
 /**
  * Process an exception that occurred.
  *
  * @param string $name
  */
 private function processException($name)
 {
     $this->dispatchEvent(FixerFileProcessedEvent::NAME, FixerFileProcessedEvent::create()->setStatus(FixerFileProcessedEvent::STATUS_EXCEPTION));
     $this->errorsManager->report(new Error(Error::TYPE_EXCEPTION, $name));
 }
 /**
  * Applies the given fixers on the input and checks the result.
  *
  * It will write the input to a temp file. The file will be fixed by a Fixer instance
  * configured with the given fixers. The result is compared with the expected output.
  * It checks if no errors were reported during the fixing.
  *
  * @param IntegrationCase $case
  */
 protected function doTest(IntegrationCase $case)
 {
     if (defined('HHVM_VERSION') && false === $case->getRequirement('hhvm')) {
         $this->markTestSkipped('HHVM is not supported.');
     }
     if (version_compare(PHP_VERSION, $case->getRequirement('php')) < 0) {
         $this->markTestSkipped(sprintf('PHP %s (or later) is required.', $case->getRequirement('php')));
     }
     $input = $case->getInputCode();
     $expected = $case->getExpectedCode();
     $input = $case->hasInputCode() ? $input : $expected;
     $this->assertNull($this->lintSource($input));
     $tmpFile = static::getTempFile();
     if (false === @file_put_contents($tmpFile, $input)) {
         throw new IOException(sprintf('Failed to write to tmp. file "%s".', $tmpFile));
     }
     $errorsManager = new ErrorsManager();
     $configProphecy = $this->prophesize('PhpCsFixer\\ConfigInterface');
     $configProphecy->usingCache()->willReturn(false);
     $configProphecy->getCacheFile()->willReturn(null);
     $configProphecy->usingLinter()->willReturn(false);
     $configProphecy->getRules()->willReturn(array());
     $configProphecy->getFinder()->willReturn(new \ArrayIterator(array(new \SplFileInfo($tmpFile))));
     $configProphecy->getFixers()->willReturn($case->getFixers());
     $runner = new Runner($configProphecy->reveal(), new SebastianBergmannDiffer(), null, $errorsManager, new NullLinter(), false);
     $result = $runner->fix();
     $changed = array_pop($result);
     if (!$errorsManager->isEmpty()) {
         $errors = $errorsManager->getExceptionErrors();
         $this->assertEmpty($errors, sprintf('Errors reported during fixing of file "%s": %s', $case->getFileName(), $this->implodeErrors($errors)));
         $errors = $errorsManager->getInvalidErrors();
         $this->assertEmpty($errors, sprintf('Errors reported during linting before fixing file "%s": %s.', $case->getFileName(), $this->implodeErrors($errors)));
         $errors = $errorsManager->getLintErrors();
         $this->assertEmpty($errors, sprintf('Errors reported during linting after fixing file "%s": %s.', $case->getFileName(), $this->implodeErrors($errors)));
     }
     if (!$case->hasInputCode()) {
         $this->assertEmpty($changed, sprintf("Expected no changes made to test \"%s\" in \"%s\".\nFixers applied:\n\"%s\".\nDiff.:\n\"%s\".", $case->getTitle(), $case->getFileName(), $changed === null ? '[None]' : implode(',', $changed['appliedFixers']), $changed === null ? '[None]' : $changed['diff']));
         return;
     }
     $this->assertNotEmpty($changed, sprintf('Expected changes made to test "%s" in "%s".', $case->getTitle(), $case->getFileName()));
     $fixedInputCode = file_get_contents($tmpFile);
     $this->assertSame($expected, $fixedInputCode, sprintf('Expected changes do not match result for "%s" in "%s".', $case->getTitle(), $case->getFileName()));
     if ($case->shouldCheckPriority()) {
         $priorities = array_map(function (FixerInterface $fixer) {
             return $fixer->getPriority();
         }, $case->getFixers());
         $this->assertNotCount(1, array_unique($priorities), sprintf('All used fixers must not have the same priority, integration tests should cover fixers with different priorities. In "%s".', $case->getFileName()));
         $tmpFile = static::getTempFile();
         if (false === @file_put_contents($tmpFile, $input)) {
             throw new IOException(sprintf('Failed to write to tmp. file "%s".', $tmpFile));
         }
         $configProphecy->getFinder()->willReturn(new \ArrayIterator(array(new \SplFileInfo($tmpFile))));
         $configProphecy->getFixers()->willReturn(array_reverse($case->getFixers()));
         $runner->fix();
         $fixedInputCodeWithReversedFixers = file_get_contents($tmpFile);
         $this->assertNotSame($fixedInputCode, $fixedInputCodeWithReversedFixers, sprintf('Set priorities must be significant. If fixers used in reverse order return same output then the integration test is not sufficient or the priority relation between used fixers should not be set. In "%s".', $case->getFileName()));
     }
     // run the test again with the `expected` part, this should always stay the same
     $this->testIntegration($case->setTitle($case->getTitle() . ' "--EXPECT-- part run"')->setInputCode(null));
 }
Esempio n. 7
0
 /**
  * @see Command
  */
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $stdErr = $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : null;
     if ($stdErr && extension_loaded('xdebug')) {
         $stdErr->writeln(sprintf($stdErr->isDecorated() ? '<bg=yellow;fg=black;>%s</>' : '%s', 'You are running php-cs-fixer with xdebug enabled. This has a major impact on runtime performance.'));
     }
     $verbosity = $output->getVerbosity();
     $resolver = new ConfigurationResolver();
     $resolver->setCwd(getcwd())->setDefaultConfig($this->defaultConfig)->setOptions(array('allow-risky' => $input->getOption('allow-risky'), 'config' => $input->getOption('config'), 'dry-run' => $input->getOption('dry-run'), 'rules' => $input->getOption('rules'), 'path' => $input->getArgument('path'), 'progress' => OutputInterface::VERBOSITY_VERBOSE <= $verbosity && 'txt' === $input->getOption('format'), 'using-cache' => $input->getOption('using-cache'), 'cache-file' => $input->getOption('cache-file'), 'format' => $input->getOption('format')))->resolve();
     $config = $resolver->getConfig();
     $configFile = $resolver->getConfigFile();
     if ($configFile && 'txt' === $input->getOption('format')) {
         $output->writeln(sprintf('Loaded config from "%s"', $configFile));
     }
     if ($config->usingLinter()) {
         try {
             $this->fixer->setLinter(new Linter($config->getPhpExecutable()));
         } catch (UnavailableLinterException $e) {
             if ($configFile && 'txt' === $input->getOption('format')) {
                 $output->writeln('Unable to use linter, can not find PHP executable');
             }
         }
     }
     $showProgress = $resolver->getProgress();
     if ($showProgress) {
         $this->fixer->setEventDispatcher($this->eventDispatcher);
         $progressOutput = new ProcessOutput($this->eventDispatcher);
     }
     $this->stopwatch->start('fixFiles');
     $changed = $this->fixer->fix($config, $resolver->isDryRun(), $input->getOption('diff'));
     $this->stopwatch->stop('fixFiles');
     if ($showProgress) {
         $progressOutput->printLegend();
         $this->fixer->setEventDispatcher(null);
     }
     $i = 1;
     switch ($resolver->getFormat()) {
         case 'txt':
             $fixerDetailLine = false;
             if (OutputInterface::VERBOSITY_VERBOSE <= $verbosity) {
                 $fixerDetailLine = $output->isDecorated() ? ' (<comment>%s</comment>)' : ' %s';
             }
             foreach ($changed as $file => $fixResult) {
                 $output->write(sprintf('%4d) %s', $i++, $file));
                 if ($fixerDetailLine) {
                     $output->write(sprintf($fixerDetailLine, implode(', ', $fixResult['appliedFixers'])));
                 }
                 if ($input->getOption('diff')) {
                     $output->writeln('');
                     $output->writeln('<comment>      ---------- begin diff ----------</comment>');
                     $output->writeln($fixResult['diff']);
                     $output->writeln('<comment>      ---------- end diff ----------</comment>');
                 }
                 $output->writeln('');
             }
             if (OutputInterface::VERBOSITY_DEBUG <= $verbosity) {
                 $output->writeln('Fixing time per file:');
                 foreach ($this->stopwatch->getSectionEvents('fixFile') as $file => $event) {
                     if ('__section__' === $file) {
                         continue;
                     }
                     $output->writeln(sprintf('[%.3f s] %s', $event->getDuration() / 1000, $file));
                 }
                 $output->writeln('');
             }
             $fixEvent = $this->stopwatch->getEvent('fixFiles');
             $output->writeln(sprintf('%s all files in %.3f seconds, %.3f MB memory used', $input->getOption('dry-run') ? 'Checked' : 'Fixed', $fixEvent->getDuration() / 1000, $fixEvent->getMemory() / 1024 / 1024));
             break;
         case 'xml':
             $dom = new \DOMDocument('1.0', 'UTF-8');
             // new nodes should be added to this or existing children
             $root = $dom->createElement('report');
             $dom->appendChild($root);
             $filesXML = $dom->createElement('files');
             $root->appendChild($filesXML);
             foreach ($changed as $file => $fixResult) {
                 $fileXML = $dom->createElement('file');
                 $fileXML->setAttribute('id', $i++);
                 $fileXML->setAttribute('name', $file);
                 $filesXML->appendChild($fileXML);
                 if (OutputInterface::VERBOSITY_VERBOSE <= $verbosity) {
                     $appliedFixersXML = $dom->createElement('applied_fixers');
                     $fileXML->appendChild($appliedFixersXML);
                     foreach ($fixResult['appliedFixers'] as $appliedFixer) {
                         $appliedFixerXML = $dom->createElement('applied_fixer');
                         $appliedFixerXML->setAttribute('name', $appliedFixer);
                         $appliedFixersXML->appendChild($appliedFixerXML);
                     }
                 }
                 if ($input->getOption('diff')) {
                     $diffXML = $dom->createElement('diff');
                     $diffXML->appendChild($dom->createCDATASection($fixResult['diff']));
                     $fileXML->appendChild($diffXML);
                 }
             }
             $fixEvent = $this->stopwatch->getEvent('fixFiles');
             $timeXML = $dom->createElement('time');
             $memoryXML = $dom->createElement('memory');
             $root->appendChild($timeXML);
             $root->appendChild($memoryXML);
             $memoryXML->setAttribute('value', round($fixEvent->getMemory() / 1024 / 1024, 3));
             $memoryXML->setAttribute('unit', 'MB');
             $timeXML->setAttribute('unit', 's');
             $timeTotalXML = $dom->createElement('total');
             $timeTotalXML->setAttribute('value', round($fixEvent->getDuration() / 1000, 3));
             $timeXML->appendChild($timeTotalXML);
             if (OutputInterface::VERBOSITY_DEBUG <= $verbosity) {
                 $timeFilesXML = $dom->createElement('files');
                 $timeXML->appendChild($timeFilesXML);
                 $eventCounter = 1;
                 foreach ($this->stopwatch->getSectionEvents('fixFile') as $file => $event) {
                     if ('__section__' === $file) {
                         continue;
                     }
                     $timeFileXML = $dom->createElement('file');
                     $timeFilesXML->appendChild($timeFileXML);
                     $timeFileXML->setAttribute('id', $eventCounter++);
                     $timeFileXML->setAttribute('name', $file);
                     $timeFileXML->setAttribute('value', round($event->getDuration() / 1000, 3));
                 }
             }
             $dom->formatOutput = true;
             $output->write($dom->saveXML());
             break;
         case 'json':
             $jFiles = array();
             foreach ($changed as $file => $fixResult) {
                 $jfile = array('name' => $file);
                 if (OutputInterface::VERBOSITY_VERBOSE <= $verbosity) {
                     $jfile['appliedFixers'] = $fixResult['appliedFixers'];
                 }
                 if ($input->getOption('diff')) {
                     $jfile['diff'] = $fixResult['diff'];
                 }
                 $jFiles[] = $jfile;
             }
             $fixEvent = $this->stopwatch->getEvent('fixFiles');
             $json = array('files' => $jFiles, 'memory' => round($fixEvent->getMemory() / 1024 / 1024, 3), 'time' => array('total' => round($fixEvent->getDuration() / 1000, 3)));
             if (OutputInterface::VERBOSITY_DEBUG <= $verbosity) {
                 $jFileTime = array();
                 foreach ($this->stopwatch->getSectionEvents('fixFile') as $file => $event) {
                     if ('__section__' === $file) {
                         continue;
                     }
                     $jFileTime[$file] = round($event->getDuration() / 1000, 3);
                 }
                 $json['time']['files'] = $jFileTime;
             }
             $output->write(json_encode($json));
             break;
     }
     $invalidErrors = $this->errorsManager->getInvalidErrors();
     if (!empty($invalidErrors)) {
         $this->listErrors($output, 'linting before fixing', $invalidErrors);
     }
     $exceptionErrors = $this->errorsManager->getExceptionErrors();
     if (!empty($exceptionErrors)) {
         $this->listErrors($output, 'fixing', $exceptionErrors);
     }
     $lintErrors = $this->errorsManager->getLintErrors();
     if (!empty($lintErrors)) {
         $this->listErrors($output, 'linting after fixing', $lintErrors);
     }
     $exitStatus = 0;
     if ($resolver->isDryRun()) {
         if (!empty($invalidErrors)) {
             $exitStatus |= self::EXIT_STATUS_FLAG_HAS_INVALID_FILES;
         }
         if (!empty($changed)) {
             $exitStatus |= self::EXIT_STATUS_FLAG_HAS_CHANGED_FILES;
         }
     }
     return $exitStatus;
 }
Esempio n. 8
0
 public function fixFile(\SplFileInfo $file, array $fixers, $dryRun, $diff, FileCacheManager $fileCacheManager)
 {
     $new = $old = file_get_contents($file->getRealPath());
     $name = $this->getFileRelativePathname($file);
     if ('' === $old || !$fileCacheManager->needFixing($name, $old) || PHP_VERSION_ID >= 50306 && PHP_VERSION_ID < 50400 && false !== stripos($old, '__halt_compiler()')) {
         $this->dispatchEvent(FixerFileProcessedEvent::NAME, FixerFileProcessedEvent::create()->setStatus(FixerFileProcessedEvent::STATUS_SKIPPED));
         return;
     }
     try {
         $this->linter->lintFile($file->getRealPath());
     } catch (LintingException $e) {
         $this->dispatchEvent(FixerFileProcessedEvent::NAME, FixerFileProcessedEvent::create()->setStatus(FixerFileProcessedEvent::STATUS_INVALID));
         $this->errorsManager->report(new Error(Error::TYPE_INVALID, $name));
         return;
     }
     $appliedFixers = array();
     // we do not need Tokens to still caching previously fixed file - so clear the cache
     Tokens::clearCache();
     $tokens = Tokens::fromCode($old);
     $newHash = $oldHash = $tokens->getCodeHash();
     try {
         foreach ($fixers as $fixer) {
             if (!$fixer->supports($file) || !$fixer->isCandidate($tokens)) {
                 continue;
             }
             $fixer->fix($file, $tokens);
             if ($tokens->isChanged()) {
                 $tokens->clearEmptyTokens();
                 $tokens->clearChanged();
                 $appliedFixers[] = $fixer->getName();
             }
         }
     } catch (\Exception $e) {
         $this->dispatchEvent(FixerFileProcessedEvent::NAME, FixerFileProcessedEvent::create()->setStatus(FixerFileProcessedEvent::STATUS_EXCEPTION));
         $this->errorsManager->report(new Error(Error::TYPE_EXCEPTION, $name));
         return;
     }
     $fixInfo = null;
     if (!empty($appliedFixers)) {
         $new = $tokens->generateCode();
         $newHash = $tokens->getCodeHash();
     }
     // We need to check if content was changed and then applied changes.
     // But we can't simple check $appliedFixers, because one fixer may revert
     // work of other and both of them will mark collection as changed.
     // Therefore we need to check if code hashes changed.
     if ($oldHash !== $newHash) {
         try {
             $this->linter->lintSource($new);
         } catch (LintingException $e) {
             $this->dispatchEvent(FixerFileProcessedEvent::NAME, FixerFileProcessedEvent::create()->setStatus(FixerFileProcessedEvent::STATUS_LINT));
             $this->errorsManager->report(new Error(Error::TYPE_LINT, $name));
             return;
         }
         if (!$dryRun && false === @file_put_contents($file->getRealPath(), $new)) {
             $error = error_get_last();
             if ($error) {
                 throw new IOException(sprintf('Failed to write file "%s", "%s".', $file->getRealpath(), $error['message']), 0, null, $file->getRealpath());
             }
             throw new IOException(sprintf('Failed to write file "%s".', $file->getRealpath()), 0, null, $file->getRealpath());
         }
         $fixInfo = array('appliedFixers' => $appliedFixers);
         if ($diff) {
             $fixInfo['diff'] = $this->stringDiff($old, $new);
         }
     }
     $fileCacheManager->setFile($name, $new);
     $this->dispatchEvent(FixerFileProcessedEvent::NAME, FixerFileProcessedEvent::create()->setStatus($fixInfo ? FixerFileProcessedEvent::STATUS_FIXED : FixerFileProcessedEvent::STATUS_NO_CHANGES));
     return $fixInfo;
 }
 public function testExitCodeActualRunWithChangedAndInvalidFiles()
 {
     $errorsManager = new ErrorsManager();
     $errorsManager->report(new Error(Error::TYPE_INVALID, 'Invalid.php'));
     $fixer = $this->getFixerMock(array('Changed.php'), $errorsManager);
     $command = new FixCommand($fixer);
     $input = $this->getInputMock(array('dry-run' => false));
     $exitCode = $command->run($input, new NullOutput());
     $this->assertSame(0, $exitCode);
 }