ProcessLintingResult.php 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. <?php
  2. declare(strict_types=1);
  3. /*
  4. * This file is part of PHP CS Fixer.
  5. *
  6. * (c) Fabien Potencier <fabien@symfony.com>
  7. * Dariusz Rumiński <dariusz.ruminski@gmail.com>
  8. *
  9. * This source file is subject to the MIT license that is bundled
  10. * with this source code in the file LICENSE.
  11. */
  12. namespace PhpCsFixer\Linter;
  13. use Symfony\Component\Process\Process;
  14. /**
  15. * @author Dariusz Rumiński <dariusz.ruminski@gmail.com>
  16. *
  17. * @internal
  18. */
  19. final class ProcessLintingResult implements LintingResultInterface
  20. {
  21. private Process $process;
  22. private ?string $path;
  23. private ?bool $isSuccessful = null;
  24. public function __construct(Process $process, ?string $path = null)
  25. {
  26. $this->process = $process;
  27. $this->path = $path;
  28. }
  29. public function check(): void
  30. {
  31. if (!$this->isSuccessful()) {
  32. // on some systems stderr is used, but on others, it's not
  33. throw new LintingException($this->getProcessErrorMessage(), $this->process->getExitCode());
  34. }
  35. }
  36. private function getProcessErrorMessage(): string
  37. {
  38. $errorOutput = $this->process->getErrorOutput();
  39. $output = strtok(ltrim('' !== $errorOutput ? $errorOutput : $this->process->getOutput()), "\n");
  40. if (false === $output) {
  41. return 'Fatal error: Unable to lint file.';
  42. }
  43. if (null !== $this->path) {
  44. $needle = sprintf('in %s ', $this->path);
  45. $pos = strrpos($output, $needle);
  46. if (false !== $pos) {
  47. $output = sprintf('%s%s', substr($output, 0, $pos), substr($output, $pos + \strlen($needle)));
  48. }
  49. }
  50. $prefix = substr($output, 0, 18);
  51. if ('PHP Parse error: ' === $prefix) {
  52. return sprintf('Parse error: %s.', substr($output, 18));
  53. }
  54. if ('PHP Fatal error: ' === $prefix) {
  55. return sprintf('Fatal error: %s.', substr($output, 18));
  56. }
  57. return sprintf('%s.', $output);
  58. }
  59. private function isSuccessful(): bool
  60. {
  61. if (null === $this->isSuccessful) {
  62. $this->process->wait();
  63. $this->isSuccessful = $this->process->isSuccessful();
  64. }
  65. return $this->isSuccessful;
  66. }
  67. }