PHPStan\Analyser\Analyser::analyse PHP Method

analyse() public method

public analyse ( array $files, Closure $progressCallback = null ) : array
$files array
$progressCallback Closure
return array errors
    public function analyse(array $files, \Closure $progressCallback = null) : array
    {
        $errors = [];
        if ($this->bootstrapFile !== null) {
            if (!is_file($this->bootstrapFile)) {
                return [sprintf('Bootstrap file %s does not exist.', $this->bootstrapFile)];
            }
            try {
                require_once $this->bootstrapFile;
            } catch (\Throwable $e) {
                return [$e->getMessage()];
            }
        }
        foreach ($this->ignoreErrors as $ignoreError) {
            try {
                \Nette\Utils\Strings::match('', $ignoreError);
            } catch (\Nette\Utils\RegexpException $e) {
                $errors[] = $e->getMessage();
            }
        }
        if (count($errors) > 0) {
            return $errors;
        }
        foreach ($files as $file) {
            try {
                if ($this->isExcludedFromAnalysing($file)) {
                    if ($progressCallback !== null) {
                        $progressCallback($file);
                    }
                    continue;
                }
                $fileErrors = [];
                $this->nodeScopeResolver->processNodes($this->parser->parseFile($file), new Scope($this->broker, $this->printer, $file), function (\PhpParser\Node $node, Scope $scope) use(&$fileErrors) {
                    if ($node instanceof \PhpParser\Node\Stmt\Trait_) {
                        return;
                    }
                    $classes = array_merge([get_class($node)], class_parents($node));
                    foreach ($this->registry->getRules($classes) as $rule) {
                        $ruleErrors = $this->createErrors($node, $scope->getAnalysedContextFile(), $rule->processNode($node, $scope));
                        $fileErrors = array_merge($fileErrors, $ruleErrors);
                    }
                });
                if ($progressCallback !== null) {
                    $progressCallback($file);
                }
                $errors = array_merge($errors, $fileErrors);
            } catch (\PhpParser\Error $e) {
                $errors[] = new Error($e->getMessage(), $file);
            } catch (\PHPStan\AnalysedCodeException $e) {
                $errors[] = new Error($e->getMessage(), $file);
            } catch (\Throwable $t) {
                $errors[] = new Error(sprintf('Internal error: %s', $t->getMessage()), $file);
            }
        }
        $unmatchedIgnoredErrors = $this->ignoreErrors;
        $errors = array_values(array_filter($errors, function (string $error) use(&$unmatchedIgnoredErrors) : bool {
            foreach ($this->ignoreErrors as $i => $ignore) {
                if (\Nette\Utils\Strings::match($error, $ignore) !== null) {
                    unset($unmatchedIgnoredErrors[$i]);
                    return false;
                }
            }
            return true;
        }));
        foreach ($unmatchedIgnoredErrors as $unmatchedIgnoredError) {
            $errors[] = sprintf('Ignored error pattern %s was not matched in reported errors.', $unmatchedIgnoredError);
        }
        return $errors;
    }

Usage Example

Ejemplo n.º 1
0
 /**
  * @param string[] $paths
  * @param \Symfony\Component\Console\Style\StyleInterface $style
  * @param bool $defaultLevelUsed
  * @return int
  */
 public function analyse(array $paths, StyleInterface $style, bool $defaultLevelUsed) : int
 {
     $errors = [];
     $files = [];
     $this->updateMemoryLimitFile();
     foreach ($paths as $path) {
         $realpath = realpath($path);
         if ($realpath === false || !file_exists($realpath)) {
             $errors[] = new Error(sprintf('<error>Path %s does not exist</error>', $path), $path);
         } elseif (is_file($realpath)) {
             $files[] = $realpath;
         } else {
             $finder = new Finder();
             foreach ($finder->files()->name('*.php')->in($realpath) as $fileInfo) {
                 $files[] = $fileInfo->getPathname();
             }
         }
     }
     $this->updateMemoryLimitFile();
     $progressStarted = false;
     $fileOrder = 0;
     $errors = array_merge($errors, $this->analyser->analyse($files, function () use($style, &$progressStarted, $files, &$fileOrder) {
         if (!$progressStarted) {
             $style->progressStart(count($files));
             $progressStarted = true;
         }
         $style->progressAdvance();
         if ($fileOrder % 100 === 0) {
             $this->updateMemoryLimitFile();
         }
         $fileOrder++;
     }));
     if ($progressStarted) {
         $style->progressFinish();
     }
     if (count($errors) === 0) {
         $style->success('No errors');
         if ($defaultLevelUsed) {
             $style->note(sprintf('PHPStan is performing only the most basic checks. You can pass a higher rule level through the --%s option (the default and current level is %d) to analyse code more thoroughly.', AnalyseCommand::OPTION_LEVEL, AnalyseCommand::DEFAULT_LEVEL));
         }
         return 0;
     }
     $currentDir = realpath(dirname($paths[0]));
     $cropFilename = function ($filename) use($currentDir) {
         if ($currentDir !== false && strpos($filename, $currentDir) === 0) {
             return substr($filename, strlen($currentDir) + 1);
         }
         return $filename;
     };
     $fileErrors = [];
     $notFileSpecificErrors = [];
     $totalErrorsCount = count($errors);
     foreach ($errors as $error) {
         if (is_string($error)) {
             $notFileSpecificErrors[] = [$error];
             continue;
         }
         if (!isset($fileErrors[$error->getFile()])) {
             $fileErrors[$error->getFile()] = [];
         }
         $fileErrors[$error->getFile()][] = $error;
     }
     foreach ($fileErrors as $file => $errors) {
         $rows = [];
         foreach ($errors as $error) {
             $rows[] = [(string) $error->getLine(), $error->getMessage()];
         }
         $style->table(['Line', $cropFilename($file)], $rows);
     }
     if (count($notFileSpecificErrors) > 0) {
         $style->table(['Error'], $notFileSpecificErrors);
     }
     $style->error(sprintf($totalErrorsCount === 1 ? 'Found %d error' : 'Found %d errors', $totalErrorsCount));
     return 1;
 }
All Usage Examples Of PHPStan\Analyser\Analyser::analyse