Skip to content
Open
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
4 changes: 2 additions & 2 deletions conf/parametersSchema.neon
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ parametersSchema:
?path: string()
?paths: listOf(string())
?count: int()
?reportUnmatched: bool()
?reportUnmatched: anyOf(bool(), 'warning')
]),
)
)
Expand All @@ -146,7 +146,7 @@ parametersSchema:
resolvedPhpDocBlockCacheCountMax: int(),
nameScopeMapMemoryCacheCountMax: int()
])
reportUnmatchedIgnoredErrors: bool()
reportUnmatchedIgnoredErrors: anyOf(bool(), 'warning')
reportIgnoresWithoutComments: bool()
typeAliases: arrayOf(string())
universalObjectCratesClasses: listOf(string())
Expand Down
45 changes: 29 additions & 16 deletions src/Analyser/AnalyserResultFinalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public function __construct(
private ScopeFactory $scopeFactory,
private LocalIgnoresProcessor $localIgnoresProcessor,
#[AutowiredParameter]
private bool $reportUnmatchedIgnoredErrors,
private bool|string $reportUnmatchedIgnoredErrors,
)
{
}
Expand Down Expand Up @@ -182,11 +182,13 @@ private function addUnmatchedIgnoredErrors(
array $locallyIgnoredCollectorErrors,
): FinalizerResult
{
if (!$this->reportUnmatchedIgnoredErrors) {
if ($this->reportUnmatchedIgnoredErrors === false) {
return new FinalizerResult($analyserResult, $collectorErrors, $locallyIgnoredCollectorErrors);
}

$isWarning = $this->reportUnmatchedIgnoredErrors === 'warning';
$errors = $analyserResult->getUnorderedErrors();
$warnings = [];
foreach ($analyserResult->getUnmatchedLineIgnores() as $file => $data) {
foreach ($data as $ignoredFile => $lines) {
if ($ignoredFile !== $file) {
Expand All @@ -195,24 +197,34 @@ private function addUnmatchedIgnoredErrors(

foreach ($lines as $line => $identifiers) {
if ($identifiers === null) {
$errors[] = (new Error(
sprintf('No error to ignore is reported on line %d.', $line),
$file,
$line,
false,
$file,
))->withIdentifier('ignore.unmatchedLine');
$message = sprintf('No error to ignore is reported on line %d.', $line);
if ($isWarning) {
$warnings[] = $message;
} else {
$errors[] = (new Error(
$message,
$file,
$line,
false,
$file,
))->withIdentifier('ignore.unmatchedLine');
}
continue;
}

foreach ($identifiers as $identifier) {
$errors[] = (new Error(
sprintf('No error with identifier %s is reported on line %d.', $identifier['name'], $line),
$file,
$line,
false,
$file,
))->withIdentifier('ignore.unmatchedIdentifier');
$message = sprintf('No error with identifier %s is reported on line %d.', $identifier['name'], $line);
if ($isWarning) {
$warnings[] = $message;
} else {
$errors[] = (new Error(
$message,
$file,
$line,
false,
$file,
))->withIdentifier('ignore.unmatchedIdentifier');
}
}
}
}
Expand All @@ -237,6 +249,7 @@ private function addUnmatchedIgnoredErrors(
),
$collectorErrors,
$locallyIgnoredCollectorErrors,
$warnings,
);
}

Expand Down
10 changes: 10 additions & 0 deletions src/Analyser/FinalizerResult.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ final class FinalizerResult
/**
* @param list<Error> $collectorErrors
* @param list<Error> $locallyIgnoredCollectorErrors
* @param list<string> $warnings
*/
public function __construct(
private AnalyserResult $analyserResult,
private array $collectorErrors,
private array $locallyIgnoredCollectorErrors,
private array $warnings = [],
)
{
}
Expand Down Expand Up @@ -46,4 +48,12 @@ public function getLocallyIgnoredCollectorErrors(): array
return $this->locallyIgnoredCollectorErrors;
}

/**
* @return list<string>
*/
public function getWarnings(): array
{
return $this->warnings;
}

}
25 changes: 20 additions & 5 deletions src/Analyser/Ignore/IgnoredErrorHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public function __construct(
#[AutowiredParameter]
private array $ignoreErrors,
#[AutowiredParameter]
private bool $reportUnmatchedIgnoredErrors,
private bool|string $reportUnmatchedIgnoredErrors,
)
{
}
Expand Down Expand Up @@ -106,10 +106,9 @@ public function initialize(): IgnoredErrorHelperResult
continue;
}

$reportUnmatched = (bool) ($uniquedExpandedIgnoreErrors[$key]['reportUnmatched'] ?? $this->reportUnmatchedIgnoredErrors);
if (!$reportUnmatched) {
$reportUnmatched = $ignoreError['reportUnmatched'] ?? $this->reportUnmatchedIgnoredErrors;
}
$existingReportUnmatched = $uniquedExpandedIgnoreErrors[$key]['reportUnmatched'] ?? $this->reportUnmatchedIgnoredErrors;
$newReportUnmatched = $ignoreError['reportUnmatched'] ?? $this->reportUnmatchedIgnoredErrors;
$reportUnmatched = self::mergeReportUnmatched($existingReportUnmatched, $newReportUnmatched);

$uniquedExpandedIgnoreErrors[$key] = [
'message' => $ignoreError['message'] ?? null,
Expand Down Expand Up @@ -159,4 +158,20 @@ public function initialize(): IgnoredErrorHelperResult
return new IgnoredErrorHelperResult($this->fileHelper, $errors, $otherIgnoreErrors, $ignoreErrorsByFile, $expandedIgnoreErrors, $this->reportUnmatchedIgnoredErrors);
}

/**
* @return bool|string true > 'warning' > false
*/
private static function mergeReportUnmatched(bool|string $a, bool|string $b): bool|string
{
if ($a === true || $b === true) {
return true;
}

if ($a === 'warning' || $b === 'warning') {
return 'warning';
}

return false;
}

}
10 changes: 10 additions & 0 deletions src/Analyser/Ignore/IgnoredErrorHelperProcessedResult.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ final class IgnoredErrorHelperProcessedResult
* @param list<Error> $notIgnoredErrors
* @param list<array{Error, mixed[]|string}> $ignoredErrors
* @param list<string> $otherIgnoreMessages
* @param list<string> $warnings
*/
public function __construct(
private array $notIgnoredErrors,
private array $ignoredErrors,
private array $otherIgnoreMessages,
private array $warnings = [],
)
{
}
Expand Down Expand Up @@ -44,4 +46,12 @@ public function getOtherIgnoreMessages(): array
return $this->otherIgnoreMessages;
}

/**
* @return list<string>
*/
public function getWarnings(): array
{
return $this->warnings;
}

}
45 changes: 31 additions & 14 deletions src/Analyser/Ignore/IgnoredErrorHelperResult.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public function __construct(
private array $otherIgnoreErrors,
private array $ignoreErrorsByFile,
private array $ignoreErrors,
private bool $reportUnmatchedIgnoredErrors,
private bool|string $reportUnmatchedIgnoredErrors,
)
{
}
Expand All @@ -54,6 +54,7 @@ public function process(
{
$unmatchedIgnoredErrors = $this->ignoreErrors;
$stringErrors = [];
$warnings = [];

$processIgnoreError = function (Error $error, int $i, $ignore) use (&$unmatchedIgnoredErrors, &$stringErrors): bool {
$shouldBeIgnored = false;
Expand Down Expand Up @@ -199,20 +200,26 @@ public function process(
if ($reportUnmatched === false) {
continue;
}
$isWarning = $reportUnmatched === 'warning';
if (
isset($unmatchedIgnoredError['count'], $unmatchedIgnoredError['realCount'])
&& (isset($unmatchedIgnoredError['realPath']) || !$onlyFiles)
) {
if ($unmatchedIgnoredError['realCount'] < $unmatchedIgnoredError['count']) {
$errors[] = (new Error(sprintf(
$message = sprintf(
'%s %s is expected to occur %d %s, but occurred only %d %s.',
IgnoredError::getIgnoredErrorLabel($unmatchedIgnoredError),
IgnoredError::stringifyPattern($unmatchedIgnoredError),
$unmatchedIgnoredError['count'],
$unmatchedIgnoredError['count'] === 1 ? 'time' : 'times',
$unmatchedIgnoredError['realCount'],
$unmatchedIgnoredError['realCount'] === 1 ? 'time' : 'times',
), $unmatchedIgnoredError['file'], $unmatchedIgnoredError['line'], false))->withIdentifier('ignore.count');
);
if ($isWarning) {
$warnings[] = $message;
} else {
$errors[] = (new Error($message, $unmatchedIgnoredError['file'], $unmatchedIgnoredError['line'], false))->withIdentifier('ignore.count');
}
}
} elseif (isset($unmatchedIgnoredError['realPath'])) {
if (!array_key_exists($unmatchedIgnoredError['realPath'], $analysedFilesKeys)) {
Expand All @@ -223,26 +230,36 @@ public function process(
continue;
}

$errors[] = (new Error(
sprintf(
'%s %s was not matched in reported errors.',
IgnoredError::getIgnoredErrorLabel($unmatchedIgnoredError),
IgnoredError::stringifyPattern($unmatchedIgnoredError),
),
$unmatchedIgnoredError['realPath'],
canBeIgnored: false,
))->withIdentifier('ignore.unmatched');
$message = sprintf(
'%s %s was not matched in reported errors.',
IgnoredError::getIgnoredErrorLabel($unmatchedIgnoredError),
IgnoredError::stringifyPattern($unmatchedIgnoredError),
);
if ($isWarning) {
$warnings[] = $message;
} else {
$errors[] = (new Error(
$message,
$unmatchedIgnoredError['realPath'],
canBeIgnored: false,
))->withIdentifier('ignore.unmatched');
}
} elseif (!$onlyFiles) {
$stringErrors[] = sprintf(
$message = sprintf(
'%s %s was not matched in reported errors.',
IgnoredError::getIgnoredErrorLabel($unmatchedIgnoredError),
IgnoredError::stringifyPattern($unmatchedIgnoredError),
);
if ($isWarning) {
$warnings[] = $message;
} else {
$stringErrors[] = $message;
}
}
}
}

return new IgnoredErrorHelperProcessedResult($errors, $ignoredErrors, $stringErrors);
return new IgnoredErrorHelperProcessedResult($errors, $ignoredErrors, $stringErrors, $warnings);
}

}
8 changes: 5 additions & 3 deletions src/Command/AnalyseApplication.php
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,12 @@ public function analyse(
$processedFiles = $intermediateAnalyserResult->getProcessedFiles();

$resultCacheResult = $resultCacheManager->process($intermediateAnalyserResult, $resultCache, $errorOutput, $onlyFiles, true);
$analyserResult = $this->analyserResultFinalizer->finalize(
$finalizerResult = $this->analyserResultFinalizer->finalize(
$this->switchTmpFileInAnalyserResult($resultCacheResult->getAnalyserResult(), $insteadOfFile, $tmpFile),
$onlyFiles,
$debug,
)->getAnalyserResult();
);
$analyserResult = $finalizerResult->getAnalyserResult();
$internalErrors = $analyserResult->getInternalErrors();
$errors = array_merge(
$analyserResult->getErrors(),
Expand Down Expand Up @@ -172,6 +173,7 @@ public function analyse(
$ignoredErrorHelperProcessedResult = $ignoredErrorHelperResult->process($errors, $onlyFiles, $files, $hasInternalErrors);
$fileSpecificErrors = $ignoredErrorHelperProcessedResult->getNotIgnoredErrors();
$notFileSpecificErrors = $ignoredErrorHelperProcessedResult->getOtherIgnoreMessages();
$warnings = array_merge($finalizerResult->getWarnings(), $ignoredErrorHelperProcessedResult->getWarnings());
$collectedData = $analyserResult->getCollectedData();
$savedResultCache = $resultCacheResult->isSaved();
}
Expand All @@ -180,7 +182,7 @@ public function analyse(
$fileSpecificErrors,
$notFileSpecificErrors,
$internalErrors,
[],
$warnings ?? [],
$this->mapCollectedData($collectedData),
$defaultLevelUsed,
$projectConfigFile,
Expand Down
4 changes: 2 additions & 2 deletions src/DependencyInjection/ValidateIgnoredErrorsExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -169,9 +169,9 @@ public function getRegistry(): UnaryOperatorTypeSpecifyingExtensionRegistry
}
}

$reportUnmatched = (bool) $builder->parameters['reportUnmatchedIgnoredErrors'];
$reportUnmatched = $builder->parameters['reportUnmatchedIgnoredErrors'];

if ($reportUnmatched) {
if ($reportUnmatched !== false) {
foreach ($ignoreErrors as $ignoreError) {
if (!is_array($ignoreError)) {
continue;
Expand Down
Loading
Loading