diff --git a/conf/config.neon b/conf/config.neon index 49e83dd82d..185502841a 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -42,7 +42,6 @@ services: - class: PHPStan\Analyser\Analyser arguments: - analyseExcludes: %excludes_analyse% ignoreErrors: %ignoreErrors% bootstrapFile: %bootstrap% @@ -70,6 +69,11 @@ services: arguments: workingDirectory: %currentWorkingDirectory% + - + class: PHPStan\File\FileExcluder + arguments: + analyseExcludes: %excludes_analyse% + - class: PHPStan\Parser\CachedParser arguments: diff --git a/src/Analyser/Analyser.php b/src/Analyser/Analyser.php index 7c7a414d63..76b4dce3a6 100644 --- a/src/Analyser/Analyser.php +++ b/src/Analyser/Analyser.php @@ -3,6 +3,7 @@ namespace PHPStan\Analyser; use PHPStan\Broker\Broker; +use PHPStan\File\FileExcluder; use PHPStan\File\FileHelper; use PHPStan\Parser\Parser; use PHPStan\Rules\Registry; @@ -36,11 +37,9 @@ class Analyser private $printer; /** - * Directories to exclude from analysing - * - * @var string[] + * @var \PHPStan\File\FileExcluder */ - private $analyseExcludes; + private $fileExcluder; /** * @var string[] @@ -52,7 +51,9 @@ class Analyser */ private $bootstrapFile; - /** @var \PHPStan\File\FileHelper */ + /** + * @var \PHPStan\File\FileHelper + */ private $fileHelper; /** @@ -61,7 +62,7 @@ class Analyser * @param \PHPStan\Rules\Registry $registry * @param \PHPStan\Analyser\NodeScopeResolver $nodeScopeResolver * @param \PhpParser\PrettyPrinter\Standard $printer - * @param string[] $analyseExcludes + * @param \PHPStan\File\FileExcluder $fileExcluder * @param string[] $ignoreErrors * @param string|null $bootstrapFile * @param \PHPStan\File\FileHelper $fileHelper @@ -72,7 +73,7 @@ public function __construct( Registry $registry, NodeScopeResolver $nodeScopeResolver, \PhpParser\PrettyPrinter\Standard $printer, - array $analyseExcludes, + FileExcluder $fileExcluder, array $ignoreErrors, string $bootstrapFile = null, FileHelper $fileHelper @@ -83,15 +84,7 @@ public function __construct( $this->registry = $registry; $this->nodeScopeResolver = $nodeScopeResolver; $this->printer = $printer; - $this->analyseExcludes = array_map(function (string $exclude) use ($fileHelper): string { - $normalized = $fileHelper->normalizePath($exclude); - - if ($this->isFnmatchPattern($normalized)) { - return $normalized; - } - - return $fileHelper->absolutizePath($normalized); - }, $analyseExcludes); + $this->fileExcluder = $fileExcluder; $this->ignoreErrors = $ignoreErrors; $this->bootstrapFile = $bootstrapFile; $this->fileHelper = $fileHelper; @@ -136,7 +129,7 @@ public function analyse(array $files, bool $onlyFiles, \Closure $progressCallbac $file = $this->fileHelper->normalizePath($file); try { - if ($this->isExcludedFromAnalysing($file)) { + if ($this->fileExcluder->isExcludedFromAnalysing($file)) { if ($progressCallback !== null) { $progressCallback($file); } @@ -217,24 +210,4 @@ private function createErrors(\PhpParser\Node $node, string $file, array $messag return $errors; } - public function isExcludedFromAnalysing(string $file): bool - { - foreach ($this->analyseExcludes as $exclude) { - if (strpos($file, $exclude) === 0) { - return true; - } - - if ($this->isFnmatchPattern($exclude) && fnmatch($exclude, $file, DIRECTORY_SEPARATOR === '\\' ? FNM_NOESCAPE : 0)) { - return true; - } - } - - return false; - } - - private function isFnmatchPattern(string $path): bool - { - return preg_match('~[*?[\]]~', $path) > 0; - } - } diff --git a/src/File/FileExcluder.php b/src/File/FileExcluder.php new file mode 100644 index 0000000000..f04b6c6dc8 --- /dev/null +++ b/src/File/FileExcluder.php @@ -0,0 +1,51 @@ +analyseExcludes = array_map(function (string $exclude) use ($fileHelper): string { + $normalized = $fileHelper->normalizePath($exclude); + + if ($this->isFnmatchPattern($normalized)) { + return $normalized; + } + + return $fileHelper->absolutizePath($normalized); + }, $analyseExcludes); + } + + public function isExcludedFromAnalysing(string $file): bool + { + foreach ($this->analyseExcludes as $exclude) { + if (strpos($file, $exclude) === 0) { + return true; + } + + if ($this->isFnmatchPattern($exclude) && fnmatch($exclude, $file, DIRECTORY_SEPARATOR === '\\' ? FNM_NOESCAPE : 0)) { + return true; + } + } + + return false; + } + + private function isFnmatchPattern(string $path): bool + { + return preg_match('~[*?[\]]~', $path) > 0; + } + +} diff --git a/tests/PHPStan/Analyser/AnalyserTest.php b/tests/PHPStan/Analyser/AnalyserTest.php index 1579353438..60e2ccff54 100644 --- a/tests/PHPStan/Analyser/AnalyserTest.php +++ b/tests/PHPStan/Analyser/AnalyserTest.php @@ -2,6 +2,7 @@ namespace PHPStan\Analyser; +use PHPStan\File\FileExcluder; use PHPStan\File\FileHelper; use PHPStan\Parser\DirectParser; use PHPStan\Rules\AlwaysFailRule; @@ -160,6 +161,7 @@ private function createAnalyser( $broker = $this->createBroker(); $printer = new \PhpParser\PrettyPrinter\Standard(); + $fileHelper = $this->getContainer()->getByType(FileHelper::class); $analyser = new Analyser( $broker, new DirectParser(new \PhpParser\Parser\Php7(new \PhpParser\Lexer()), $traverser), @@ -176,10 +178,10 @@ private function createAnalyser( [] ), $printer, - $analyseExcludes, + new FileExcluder($fileHelper, $analyseExcludes), $ignoreErrors, $bootstrapFile, - $this->getContainer()->getByType(FileHelper::class) + $fileHelper ); return $analyser; diff --git a/tests/PHPStan/Rules/AbstractRuleTest.php b/tests/PHPStan/Rules/AbstractRuleTest.php index eb4ad8d566..34cafa7fb2 100644 --- a/tests/PHPStan/Rules/AbstractRuleTest.php +++ b/tests/PHPStan/Rules/AbstractRuleTest.php @@ -6,6 +6,7 @@ use PHPStan\Analyser\Error; use PHPStan\Analyser\NodeScopeResolver; use PHPStan\Analyser\TypeSpecifier; +use PHPStan\File\FileExcluder; use PHPStan\File\FileHelper; use PHPStan\Type\FileTypeMapper; @@ -31,6 +32,7 @@ private function getAnalyser(): Analyser $broker = $this->createBroker(); $printer = new \PhpParser\PrettyPrinter\Standard(); + $fileHelper = $this->getFileHelper(); $this->analyser = new Analyser( $broker, $this->getParser(), @@ -47,10 +49,10 @@ private function getAnalyser(): Analyser [] ), $printer, - [], + new FileExcluder($fileHelper, []), [], null, - $this->getFileHelper() + $fileHelper ); }