Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
"nette/utils": "^3.2.5",
"nikic/php-parser": "^5.7.0",
"ondram/ci-detector": "^4.0",
"helgesverre/toon": "^1.0",
"shipfastlabs/agent-detector": "^1.0",
Comment on lines +27 to +28
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder what's your policy about added library in PHPStan @ondrejmirtes ?
Adding library with low number of star and/or low number of contributors/maintainers is always a risk (especially for security reason).
I always have this story in mind

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not worth it here...

"ondrejmirtes/better-reflection": "6.65.0.9",
"ondrejmirtes/composer-attribute-collector": "^1.1.1",
"ondrejmirtes/php-merge": "^4.1",
Expand Down
135 changes: 134 additions & 1 deletion composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions conf/services.neon
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,9 @@ services:
arguments:
pretty: true

errorFormatter.toon:
class: PHPStan\Command\ErrorFormatter\ToonErrorFormatter

stubFileTypeMapper:
class: PHPStan\Type\FileTypeMapper
arguments:
Expand Down
12 changes: 11 additions & 1 deletion src/Command/AnalyseCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use OndraM\CiDetector\CiDetector;
use Override;
use PHPStan\Analyser\InternalError;
use PHPStan\Command\ErrorFormatter\AgentDetectedErrorFormatter;
use PHPStan\Command\ErrorFormatter\BaselineNeonErrorFormatter;
use PHPStan\Command\ErrorFormatter\BaselinePhpErrorFormatter;
use PHPStan\Command\ErrorFormatter\ErrorFormatter;
Expand Down Expand Up @@ -235,11 +236,20 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$errorFormat = $inceptionResult->getContainer()->getParameter('errorFormat');
}

$container = $inceptionResult->getContainer();

if ($errorFormat === null) {
/** @var AgentDetectedErrorFormatter $agentFormatter */
$agentFormatter = $container->getByType(AgentDetectedErrorFormatter::class);
if ($agentFormatter->isAgentDetected()) {
$errorFormat = 'toon';
}
}

if ($errorFormat === null) {
$errorFormat = 'table';
}

$container = $inceptionResult->getContainer();
$errorFormatterServiceName = sprintf('errorFormatter.%s', $errorFormat);
if (!$container->hasService($errorFormatterServiceName)) {
$errorOutput->writeLineFormatted(sprintf(
Expand Down
35 changes: 35 additions & 0 deletions src/Command/ErrorFormatter/AgentDetectedErrorFormatter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php declare(strict_types = 1);

namespace PHPStan\Command\ErrorFormatter;

use AgentDetector\AgentDetector;
use PHPStan\Command\AnalysisResult;
use PHPStan\Command\Output;
use PHPStan\DependencyInjection\AutowiredParameter;
use PHPStan\DependencyInjection\AutowiredService;

/**
* @api
*/
#[AutowiredService(as: AgentDetectedErrorFormatter::class)]
final class AgentDetectedErrorFormatter implements ErrorFormatter
{

public function __construct(
#[AutowiredParameter(ref: '@errorFormatter.toon')]
private ToonErrorFormatter $toonErrorFormatter,
)
{
}

public function isAgentDetected(): bool
{
return AgentDetector::detect()->isAgent;
}

public function formatErrors(AnalysisResult $analysisResult, Output $output): int
{
return $this->toonErrorFormatter->formatErrors($analysisResult, $output);
}

}
65 changes: 65 additions & 0 deletions src/Command/ErrorFormatter/ToonErrorFormatter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php declare(strict_types = 1);

namespace PHPStan\Command\ErrorFormatter;

use HelgeSverre\Toon\Toon;
use PHPStan\Command\AnalysisResult;
use PHPStan\Command\Output;
use Symfony\Component\Console\Formatter\OutputFormatter;
use function count;

final class ToonErrorFormatter implements ErrorFormatter
{

public function formatErrors(AnalysisResult $analysisResult, Output $output): int
{
$errorsArray = [
'totals' => [
'errors' => count($analysisResult->getNotFileSpecificErrors()),
'file_errors' => count($analysisResult->getFileSpecificErrors()),
],
'files' => [],
'errors' => [],
];

$tipFormatter = new OutputFormatter(false);

foreach ($analysisResult->getFileSpecificErrors() as $fileSpecificError) {
$file = $fileSpecificError->getFile();
if (!isset($errorsArray['files'][$file])) {
$errorsArray['files'][$file] = [
'errors' => 0,
'messages' => [],
];
}
$errorsArray['files'][$file]['errors']++;

$message = [
'message' => $fileSpecificError->getMessage(),
'line' => $fileSpecificError->getLine(),
'ignorable' => $fileSpecificError->canBeIgnored(),
];

if ($fileSpecificError->getTip() !== null) {
$message['tip'] = $tipFormatter->format($fileSpecificError->getTip());
}

if ($fileSpecificError->getIdentifier() !== null) {
$message['identifier'] = $fileSpecificError->getIdentifier();
}

$errorsArray['files'][$file]['messages'][] = $message;
}

foreach ($analysisResult->getNotFileSpecificErrors() as $notFileSpecificError) {
$errorsArray['errors'][] = $notFileSpecificError;
}

$toon = Toon::encode($errorsArray);

$output->writeRaw($toon);

return $analysisResult->hasErrors() ? 1 : 0;
}

}
13 changes: 11 additions & 2 deletions src/Command/ErrorsConsoleStyle.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace PHPStan\Command;

use AgentDetector\AgentDetector;
use OndraM\CiDetector\CiDetector;
use Override;
use Symfony\Component\Console\Helper\Helper;
Expand Down Expand Up @@ -29,6 +30,8 @@ final class ErrorsConsoleStyle extends SymfonyStyle

private ?bool $isCiDetected = null;

private ?bool $isAgentDetected = null;

public function __construct(InputInterface $input, OutputInterface $output)
{
parent::__construct($input, $output);
Expand All @@ -45,6 +48,11 @@ private function isCiDetected(): bool
return $this->isCiDetected;
}

private function isAgentDetected(): bool
{
return $this->isAgentDetected ??= AgentDetector::detect()->isAgent;
}

/**
* @param string[] $headers
* @param string[][] $rows
Expand Down Expand Up @@ -95,9 +103,10 @@ public function createProgressBar(int $max = 0): ProgressBar
}

$ci = $this->isCiDetected();
$this->progressBar->setOverwrite(!$ci);
$agent = $this->isAgentDetected();
$this->progressBar->setOverwrite(!$ci && !$agent);

if ($ci) {
if ($ci || $agent) {
$this->progressBar->minSecondsBetweenRedraws(15);
$this->progressBar->maxSecondsBetweenRedraws(30);
} elseif (DIRECTORY_SEPARATOR === '\\') {
Expand Down
Loading
Loading