Skip to content
14 changes: 13 additions & 1 deletion bin/phpstan-baseline-analyze.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,17 @@
$format = ResultPrinter::FORMAT_JSON;
}

$exitCode = $app->start($argv[1], $format);
$excludeOptions = preg_grep('/^--exclude=/', $argv);
if ($excludeOptions) {
$excludedFiles = preg_replace('/^--exclude=/', '', $excludeOptions);

Check failure on line 43 in bin/phpstan-baseline-analyze.php

View workflow job for this annotation

GitHub Actions / phpstan static code analysis (ubuntu-latest, 8.2)

Parameter #3 $subject of function preg_replace expects array<float|int|string>|string, array given.

Check failure on line 43 in bin/phpstan-baseline-analyze.php

View workflow job for this annotation

GitHub Actions / phpstan static code analysis (ubuntu-latest, 8.0)

Parameter #3 $subject of function preg_replace expects array<float|int|string>|string, array given.

Check failure on line 43 in bin/phpstan-baseline-analyze.php

View workflow job for this annotation

GitHub Actions / phpstan static code analysis (ubuntu-latest, 7.4)

Parameter #3 $subject of function preg_replace expects array<float|int|string>|string, array given.
} else {
$excludedFiles = [];
}

if (in_array('--summary', $argv)) {
$exitCode = $app->summarize($argv[1], $format, $excludedFiles);
} else {
$exitCode = $app->start($argv[1], $format);
}

exit($exitCode);
58 changes: 58 additions & 0 deletions lib/AnalyzeApplication.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace staabm\PHPStanBaselineAnalysis;

use DateTimeImmutable;
use \Iterator;

final class AnalyzeApplication
Expand Down Expand Up @@ -51,6 +52,45 @@ public function start(string $glob, string $format): int
return self::EXIT_ERROR;
}

/**
* @param string[] $excludedFilenames
*/
public function summarize(string $glob, string $format, array $excludedFilenames = []): int
{
$baselines = BaselineFinder::forGlob($glob, $excludedFilenames);
$numBaselines = count($baselines);
if ($numBaselines === 0) {
return self::EXIT_ERROR;
}

$resultSummary = new AnalyzerResult();
$baselineSummary = new Baseline();

foreach ($baselines as $baseline) {
$analyzer = new BaselineAnalyzer($baseline);
$result = $analyzer->analyze();
$resultSummary->referenceDate = new DateTimeImmutable();
$resultSummary->overallErrors += $result->overallErrors;
$resultSummary->deprecations += $result->deprecations;
$resultSummary->invalidPhpdocs += $result->invalidPhpdocs;
$resultSummary->unknownTypes += $result->unknownTypes;
$resultSummary->anonymousVariables += $result->anonymousVariables;
$resultSummary->unusedSymbols += $result->unusedSymbols;
}

$printer = new ResultPrinter();

if ($format == ResultPrinter::FORMAT_JSON) {
$stream = $printer->streamJson($baselineSummary, $resultSummary);
} else {
$stream = $printer->streamText($baselineSummary, $resultSummary);
}

$this->printSummary($format, $stream);

return self::EXIT_SUCCESS;
}

/**
* @api
*/
Expand Down Expand Up @@ -84,4 +124,22 @@ private function printResult(string $format, bool $isFirst, bool $isLast, Iterat
}
}
}

/**
* @param Iterator<string> $stream
*/
private function printSummary(string $format, Iterator $stream): void
{
if ($format === ResultPrinter::FORMAT_JSON) {
printf('[');
}

foreach ($stream as $string) {
printf($string);
}

if ($format === ResultPrinter::FORMAT_JSON) {
printf(']');
}
}
}
2 changes: 1 addition & 1 deletion lib/Baseline.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,6 @@
}

public function getFilePath():string {
return $this->filePath;
return $this->filePath ? : basename(getcwd());

Check failure on line 62 in lib/Baseline.php

View workflow job for this annotation

GitHub Actions / phpstan static code analysis (ubuntu-latest, 8.2)

Parameter #1 $path of function basename expects string, string|false given.

Check failure on line 62 in lib/Baseline.php

View workflow job for this annotation

GitHub Actions / phpstan static code analysis (ubuntu-latest, 8.0)

Parameter #1 $path of function basename expects string, string|false given.

Check failure on line 62 in lib/Baseline.php

View workflow job for this annotation

GitHub Actions / phpstan static code analysis (ubuntu-latest, 7.4)

Parameter #1 $path of function basename expects string, string|false given.
}
}
33 changes: 29 additions & 4 deletions lib/BaselineFinder.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@
final class BaselineFinder
{
/**
* @param string[] $excludeFilenames
* @return Baseline[]
*/
static public function forGlob(string $glob): array
static public function forGlob(string $glob, array $excludeFilenames = []): array
{
$baselines = [];

foreach (self::rglob($glob) as $baseline) {
foreach (self::rglob($glob, 0, $excludeFilenames) as $baseline) {
if (!is_file($baseline)) {
continue;
}
Expand All @@ -29,22 +30,46 @@ static public function forGlob(string $glob): array
/**
* from https://stackoverflow.com/a/17161106
*
* @param string[] $excludeFilenames
* @return string[]
*/
static private function rglob(string $pattern,int $flags = 0):array
static private function rglob(string $pattern, int $flags = 0, array $excludeFilenames = []): array
{
$files = glob($pattern, $flags);
if (!$files) {
return [];
}

// Filter out excluded filenames
if ($excludeFilenames !== []) {
$files = self::filerExcludedFiles($files, $excludeFilenames);
}

foreach (glob(dirname($pattern) . '/*', GLOB_ONLYDIR | GLOB_NOSORT) ?: [] as $dir) {
if (basename($dir) == 'vendor') {
continue;
}

$files = array_merge($files, self::rglob($dir . '/' . basename($pattern), $flags));
$files = array_merge($files, self::rglob($dir . '/' . basename($pattern), $flags, $excludeFilenames));
}
return $files;
}

/**
* @param string[] $files
* @param string[] $excludeFilenames
* @return string[]
*/
private static function filerExcludedFiles(array $files, array $excludeFilenames): array
{
return array_filter($files, function (string $file) use ($excludeFilenames) {
foreach ($excludeFilenames as $excludeFilename) {
if (str_ends_with($file, $excludeFilename)) {
return false;
}
}

return true;
});
}
}
Loading