From 105e83ea4729a24015cf7993b8dc832b2122ce2e Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 18 May 2019 12:44:22 +0200 Subject: [PATCH] Allow multiple paths per ignore --- README.md | 6 ++++-- conf/config.neon | 4 ++++ src/Analyser/Analyser.php | 14 ++++++++++++-- src/Analyser/IgnoredError.php | 17 ++++++++++------- tests/PHPStan/Analyser/AnalyserTest.php | 14 +++++++++++++- 5 files changed, 43 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index bb51ee9a6d..ea031d1054 100644 --- a/README.md +++ b/README.md @@ -332,7 +332,7 @@ parameters: - '#Call to an undefined method PHPUnit_Framework_MockObject_MockObject::[a-zA-Z0-9_]+\(\)#' ``` -To exclude an error in a specific directory or file, specify a `path` along with the `message`: +To exclude an error in a specific directory or file, specify a `path` or `paths` along with the `message`: ``` parameters: @@ -342,7 +342,9 @@ parameters: path: %currentWorkingDirectory%/some/dir/SomeFile.php - message: '#Call to an undefined method [a-zA-Z0-9\\_]+::method\(\)#' - path: %currentWorkingDirectory%/other/dir/* + paths: + - %currentWorkingDirectory%/some/dir/* + - %currentWorkingDirectory%/other/dir/* - '#Other error to catch anywhere#' ``` diff --git a/conf/config.neon b/conf/config.neon index 7350951b58..e1936786fa 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -120,6 +120,10 @@ parametersSchema: structure([ message: string() path: string() + ]), + structure([ + message: string() + paths: listOf(string()) ]) ) ) diff --git a/src/Analyser/Analyser.php b/src/Analyser/Analyser.php index d5f5f1262e..38760db0ee 100644 --- a/src/Analyser/Analyser.php +++ b/src/Analyser/Analyser.php @@ -104,7 +104,7 @@ public function analyse( ); continue; } - if (!isset($ignoreError['path'])) { + if (!isset($ignoreError['path']) && !isset($ignoreError['paths'])) { $errors[] = sprintf( 'Ignored error %s is missing a path.', Json::encode($ignoreError) @@ -240,7 +240,11 @@ function (\PhpParser\Node $node, Scope $scope) use (&$fileErrors, $file, &$scope $errors = array_values(array_filter($errors, function (Error $error) use (&$unmatchedIgnoredErrors, &$addErrors): bool { foreach ($this->ignoreErrors as $i => $ignore) { if (IgnoredError::shouldIgnore($this->fileHelper, $error, $ignore)) { - unset($unmatchedIgnoredErrors[$i]); + if (is_string($ignore)) { + unset($unmatchedIgnoredErrors[$i]); + } elseif (!isset($ignore['paths'])) { + unset($unmatchedIgnoredErrors[$i]); + } if (!$error->canBeIgnored()) { $addErrors[] = sprintf( 'Error message "%s" cannot be ignored, use excludes_analyse instead.', @@ -259,6 +263,12 @@ function (\PhpParser\Node $node, Scope $scope) use (&$fileErrors, $file, &$scope if (!$onlyFiles && $this->reportUnmatchedIgnoredErrors && !$reachedInternalErrorsCountLimit) { foreach ($unmatchedIgnoredErrors as $unmatchedIgnoredError) { + if ( + is_array($unmatchedIgnoredError) + && isset($unmatchedIgnoredError['paths']) + ) { + continue; + } $errors[] = sprintf( 'Ignored error pattern %s was not matched in reported errors.', IgnoredError::stringifyPattern($unmatchedIgnoredError) diff --git a/src/Analyser/IgnoredError.php b/src/Analyser/IgnoredError.php index 4d920a4fe1..4b49b66228 100644 --- a/src/Analyser/IgnoredError.php +++ b/src/Analyser/IgnoredError.php @@ -31,7 +31,7 @@ public static function stringifyPattern($ignoredError): string * @phpcsSuppress SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingParameterTypeHint * @param FileHelper $fileHelper * @param Error $error - * @param array|string $ignoredError + * @param mixed[]|string $ignoredError * @return bool To ignore or not to ignore? */ public static function shouldIgnore( @@ -41,15 +41,18 @@ public static function shouldIgnore( ): bool { if (is_array($ignoredError)) { - // ignore by path if (isset($ignoredError['path'])) { - $fileExcluder = new FileExcluder($fileHelper, [$ignoredError['path']]); - - return \Nette\Utils\Strings::match($error->getMessage(), $ignoredError['message']) !== null - && $fileExcluder->isExcludedFromAnalysing($error->getFile()); + $ignoredPaths = [$ignoredError['path']]; + } elseif (isset($ignoredError['paths'])) { + $ignoredPaths = $ignoredError['paths']; + } else { + throw new \PHPStan\ShouldNotHappenException(); } - throw new \PHPStan\ShouldNotHappenException(); + $fileExcluder = new FileExcluder($fileHelper, $ignoredPaths); + + return \Nette\Utils\Strings::match($error->getMessage(), $ignoredError['message']) !== null + && $fileExcluder->isExcludedFromAnalysing($error->getFile()); } return \Nette\Utils\Strings::match($error->getMessage(), $ignoredError) !== null; diff --git a/tests/PHPStan/Analyser/AnalyserTest.php b/tests/PHPStan/Analyser/AnalyserTest.php index 1fd3eceed6..8277426d70 100644 --- a/tests/PHPStan/Analyser/AnalyserTest.php +++ b/tests/PHPStan/Analyser/AnalyserTest.php @@ -70,6 +70,18 @@ public function testIgnoreErrorByPath(): void $this->assertCount(0, $result); } + public function testIgnoreErrorByPaths(): void + { + $ignoreErrors = [ + [ + 'message' => '#Fail\.#', + 'paths' => [__DIR__ . '/data/bootstrap-error.php'], + ], + ]; + $result = $this->runAnalyser($ignoreErrors, true, __DIR__ . '/data/bootstrap-error.php', false); + $this->assertCount(0, $result); + } + public function testIgnoreErrorNotFoundInPath(): void { $ignoreErrors = [ @@ -144,7 +156,7 @@ public function testReportMultipleParserErrorsAtOnce(): void } /** - * @param string[]|array> $ignoreErrors + * @param mixed[] $ignoreErrors * @param bool $reportUnmatchedIgnoredErrors * @param string $filePath * @param bool $onlyFiles