2016-06-10 00:08:25 +02:00
|
|
|
<?php
|
2016-08-13 20:20:46 +02:00
|
|
|
namespace Psalm\Checker;
|
2016-06-10 00:08:25 +02:00
|
|
|
|
2016-08-13 20:20:46 +02:00
|
|
|
use Psalm\Config;
|
2016-08-14 01:44:24 +02:00
|
|
|
use Psalm\Exception;
|
2016-11-02 07:29:00 +01:00
|
|
|
use Psalm\IssueBuffer;
|
|
|
|
use RecursiveDirectoryIterator;
|
|
|
|
use RecursiveIteratorIterator;
|
2016-08-13 20:20:46 +02:00
|
|
|
|
2016-06-10 00:08:25 +02:00
|
|
|
class ProjectChecker
|
|
|
|
{
|
2016-06-26 19:45:20 +02:00
|
|
|
/**
|
|
|
|
* Cached config
|
2016-11-02 07:29:00 +01:00
|
|
|
*
|
2016-06-26 19:45:20 +02:00
|
|
|
* @var Config|null
|
|
|
|
*/
|
2016-12-08 04:38:57 +01:00
|
|
|
protected $config;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var self
|
|
|
|
*/
|
|
|
|
public static $instance;
|
2016-06-26 19:45:20 +02:00
|
|
|
|
2016-07-25 21:05:58 +02:00
|
|
|
/**
|
|
|
|
* Whether or not to use colors in error output
|
2016-11-02 07:29:00 +01:00
|
|
|
*
|
2016-07-25 21:05:58 +02:00
|
|
|
* @var boolean
|
|
|
|
*/
|
2016-12-08 04:38:57 +01:00
|
|
|
public $use_color;
|
2016-07-25 21:05:58 +02:00
|
|
|
|
2016-08-04 20:38:43 +02:00
|
|
|
/**
|
|
|
|
* Whether or not to show informational messages
|
2016-11-02 07:29:00 +01:00
|
|
|
*
|
2016-08-04 20:38:43 +02:00
|
|
|
* @var boolean
|
|
|
|
*/
|
2016-12-08 04:38:57 +01:00
|
|
|
public $show_info;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var string
|
|
|
|
*/
|
|
|
|
public $output_format;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @var array<string, string>
|
|
|
|
*/
|
|
|
|
public $fake_files = [];
|
|
|
|
|
|
|
|
const TYPE_CONSOLE = 'console';
|
|
|
|
const TYPE_JSON = 'json';
|
|
|
|
|
2016-12-17 06:48:31 +01:00
|
|
|
/**
|
|
|
|
* @param boolean $use_color
|
|
|
|
* @param boolean $show_info
|
|
|
|
* @param string $output_format
|
|
|
|
*/
|
2016-12-08 04:38:57 +01:00
|
|
|
public function __construct($use_color = true, $show_info = true, $output_format = self::TYPE_CONSOLE)
|
|
|
|
{
|
|
|
|
$this->use_color = $use_color;
|
|
|
|
$this->show_info = $show_info;
|
|
|
|
|
|
|
|
if (!in_array($output_format, [self::TYPE_CONSOLE, self::TYPE_JSON])) {
|
|
|
|
throw new \UnexpectedValueException('Unrecognised output format ' . $output_format);
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->output_format = $output_format;
|
|
|
|
self::$instance = $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return self
|
|
|
|
*/
|
|
|
|
public static function getInstance()
|
|
|
|
{
|
|
|
|
return self::$instance;
|
|
|
|
}
|
2016-08-04 20:38:43 +02:00
|
|
|
|
2016-10-15 06:12:57 +02:00
|
|
|
/**
|
|
|
|
* @param boolean $debug
|
|
|
|
* @param boolean $is_diff
|
2016-11-13 17:24:46 +01:00
|
|
|
* @param boolean $update_docblocks
|
2016-10-15 06:12:57 +02:00
|
|
|
* @return void
|
|
|
|
*/
|
2016-12-08 04:38:57 +01:00
|
|
|
public function check($debug = false, $is_diff = false, $update_docblocks = false)
|
2016-06-13 21:33:18 +02:00
|
|
|
{
|
2016-10-15 06:12:57 +02:00
|
|
|
$cwd = getcwd();
|
|
|
|
|
2016-11-06 05:59:29 +01:00
|
|
|
$start_checks = (int)microtime(true);
|
|
|
|
|
2016-10-15 06:12:57 +02:00
|
|
|
if (!$cwd) {
|
|
|
|
throw new \InvalidArgumentException('Cannot work with empty cwd');
|
|
|
|
}
|
|
|
|
|
2016-12-08 04:38:57 +01:00
|
|
|
if (!$this->config) {
|
|
|
|
$this->config = self::getConfigForPath($cwd);
|
2016-06-26 21:33:51 +02:00
|
|
|
}
|
2016-06-26 19:45:20 +02:00
|
|
|
|
2016-10-07 06:58:08 +02:00
|
|
|
$diff_files = null;
|
2016-10-07 19:26:29 +02:00
|
|
|
$deleted_files = null;
|
2016-10-05 19:24:46 +02:00
|
|
|
|
2016-10-07 06:58:08 +02:00
|
|
|
if ($is_diff && FileChecker::loadReferenceCache() && FileChecker::canDiffFiles()) {
|
2016-10-07 19:26:29 +02:00
|
|
|
$deleted_files = FileChecker::getDeletedReferencedFiles();
|
|
|
|
$diff_files = $deleted_files;
|
2016-10-07 06:58:08 +02:00
|
|
|
|
2016-12-29 16:24:10 +01:00
|
|
|
foreach ($this->config->getProjectDirectories() as $dir_name) {
|
2016-12-08 04:38:57 +01:00
|
|
|
$diff_files = array_merge($diff_files, self::getDiffFilesInDir($dir_name, $this->config));
|
2016-10-07 06:58:08 +02:00
|
|
|
}
|
2016-10-05 19:24:46 +02:00
|
|
|
}
|
2016-10-07 06:58:08 +02:00
|
|
|
|
2016-11-06 05:59:29 +01:00
|
|
|
$files_checked = [];
|
|
|
|
|
2016-10-07 19:26:29 +02:00
|
|
|
if ($diff_files === null || $deleted_files === null || count($diff_files) > 200) {
|
2016-12-29 16:24:10 +01:00
|
|
|
foreach ($this->config->getProjectDirectories() as $dir_name) {
|
2016-12-08 04:38:57 +01:00
|
|
|
$this->checkDirWithConfig($dir_name, $this->config, $debug, $update_docblocks);
|
2016-10-05 19:24:46 +02:00
|
|
|
}
|
2016-11-02 07:29:00 +01:00
|
|
|
} else {
|
2016-10-07 06:58:08 +02:00
|
|
|
if ($debug) {
|
|
|
|
echo count($diff_files) . ' changed files' . PHP_EOL;
|
|
|
|
}
|
2016-06-21 01:30:38 +02:00
|
|
|
|
2016-10-07 06:58:08 +02:00
|
|
|
$file_list = self::getReferencedFilesFromDiff($diff_files);
|
2016-11-02 07:29:00 +01:00
|
|
|
|
2016-10-07 19:26:29 +02:00
|
|
|
// strip out deleted files
|
|
|
|
$file_list = array_diff($file_list, $deleted_files);
|
2016-12-08 04:38:57 +01:00
|
|
|
$this->checkDiffFilesWithConfig($this->config, $debug, $file_list);
|
2016-10-07 06:58:08 +02:00
|
|
|
}
|
|
|
|
|
2016-11-06 05:59:29 +01:00
|
|
|
$removed_parser_files = FileChecker::deleteOldParserCaches(
|
|
|
|
$is_diff ? FileChecker::getLastGoodRun() : $start_checks
|
|
|
|
);
|
|
|
|
|
|
|
|
if ($debug && $removed_parser_files) {
|
|
|
|
echo 'Removed ' . $removed_parser_files . ' old parser caches' . PHP_EOL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($is_diff) {
|
2016-12-08 04:38:57 +01:00
|
|
|
FileChecker::touchParserCaches($this->getAllFiles($this->config), $start_checks);
|
2016-11-06 05:59:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
IssueBuffer::finish(true, (int)$start_checks);
|
2016-06-13 21:33:18 +02:00
|
|
|
}
|
|
|
|
|
2016-10-15 06:12:57 +02:00
|
|
|
/**
|
|
|
|
* @param string $dir_name
|
|
|
|
* @param boolean $debug
|
2016-11-13 17:24:46 +01:00
|
|
|
* @param boolean $update_docblocks
|
2016-10-15 06:12:57 +02:00
|
|
|
* @return void
|
|
|
|
*/
|
2016-12-08 04:38:57 +01:00
|
|
|
public function checkDir($dir_name, $debug = false, $update_docblocks = false)
|
2016-06-10 00:08:25 +02:00
|
|
|
{
|
2016-12-08 04:38:57 +01:00
|
|
|
if (!$this->config) {
|
|
|
|
$this->config = self::getConfigForPath($dir_name);
|
|
|
|
$this->config->hide_external_errors = $this->config->isInProjectDirs(
|
|
|
|
$this->config->shortenFileName($dir_name)
|
2016-11-02 07:29:00 +01:00
|
|
|
);
|
2016-06-26 19:45:20 +02:00
|
|
|
}
|
2016-06-10 00:08:25 +02:00
|
|
|
|
2016-10-05 19:24:46 +02:00
|
|
|
FileChecker::loadReferenceCache();
|
|
|
|
|
2016-12-08 04:38:57 +01:00
|
|
|
$this->checkDirWithConfig($dir_name, $this->config, $debug, $update_docblocks);
|
2016-06-26 21:25:38 +02:00
|
|
|
|
|
|
|
IssueBuffer::finish();
|
|
|
|
}
|
|
|
|
|
2016-10-15 06:12:57 +02:00
|
|
|
/**
|
|
|
|
* @param string $dir_name
|
|
|
|
* @param Config $config
|
|
|
|
* @param bool $debug
|
2016-11-13 17:24:46 +01:00
|
|
|
* @param bool $update_docblocks
|
2016-10-15 06:12:57 +02:00
|
|
|
* @return void
|
|
|
|
*/
|
2016-12-08 04:38:57 +01:00
|
|
|
protected function checkDirWithConfig($dir_name, Config $config, $debug, $update_docblocks)
|
2016-06-26 21:25:38 +02:00
|
|
|
{
|
|
|
|
$file_extensions = $config->getFileExtensions();
|
|
|
|
$filetype_handlers = $config->getFiletypeHandlers();
|
2016-06-13 21:33:18 +02:00
|
|
|
|
|
|
|
/** @var RecursiveDirectoryIterator */
|
2016-06-28 20:28:45 +02:00
|
|
|
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir_name));
|
2016-06-13 21:33:18 +02:00
|
|
|
$iterator->rewind();
|
|
|
|
|
|
|
|
while ($iterator->valid()) {
|
|
|
|
if (!$iterator->isDot()) {
|
2016-06-20 06:38:13 +02:00
|
|
|
$extension = $iterator->getExtension();
|
|
|
|
if (in_array($extension, $file_extensions)) {
|
2016-10-15 06:12:57 +02:00
|
|
|
$file_name = (string)$iterator->getRealPath();
|
2016-06-20 06:38:13 +02:00
|
|
|
|
|
|
|
if ($debug) {
|
|
|
|
echo 'Checking ' . $file_name . PHP_EOL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isset($filetype_handlers[$extension])) {
|
|
|
|
/** @var FileChecker */
|
|
|
|
$file_checker = new $filetype_handlers[$extension]($file_name);
|
2016-11-02 07:29:00 +01:00
|
|
|
} else {
|
2016-06-20 06:38:13 +02:00
|
|
|
$file_checker = new FileChecker($file_name);
|
|
|
|
}
|
|
|
|
|
2016-11-13 00:51:48 +01:00
|
|
|
$file_checker->check(true, true, null, true, $update_docblocks);
|
2016-06-13 21:33:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$iterator->next();
|
|
|
|
}
|
2016-06-20 06:38:13 +02:00
|
|
|
}
|
2016-06-10 00:08:25 +02:00
|
|
|
|
2016-11-07 23:07:59 +01:00
|
|
|
/**
|
|
|
|
* @param Config $config
|
|
|
|
* @return array<int, string>
|
|
|
|
*/
|
2016-12-08 04:38:57 +01:00
|
|
|
protected function getAllFiles(Config $config)
|
2016-11-06 05:59:29 +01:00
|
|
|
{
|
|
|
|
$file_extensions = $config->getFileExtensions();
|
|
|
|
$file_names = [];
|
|
|
|
|
2016-12-29 16:24:10 +01:00
|
|
|
foreach ($config->getProjectDirectories() as $dir_name) {
|
2016-11-06 05:59:29 +01:00
|
|
|
/** @var RecursiveDirectoryIterator */
|
|
|
|
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir_name));
|
|
|
|
$iterator->rewind();
|
|
|
|
|
|
|
|
while ($iterator->valid()) {
|
|
|
|
if (!$iterator->isDot()) {
|
|
|
|
$extension = $iterator->getExtension();
|
|
|
|
if (in_array($extension, $file_extensions)) {
|
|
|
|
$file_names[] = (string)$iterator->getRealPath();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$iterator->next();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $file_names;
|
|
|
|
}
|
|
|
|
|
2016-10-15 06:12:57 +02:00
|
|
|
/**
|
|
|
|
* @param string $dir_name
|
|
|
|
* @param Config $config
|
|
|
|
* @return array<string>
|
|
|
|
*/
|
2016-10-07 06:58:08 +02:00
|
|
|
protected static function getDiffFilesInDir($dir_name, Config $config)
|
|
|
|
{
|
|
|
|
$file_extensions = $config->getFileExtensions();
|
|
|
|
$filetype_handlers = $config->getFiletypeHandlers();
|
|
|
|
|
|
|
|
/** @var RecursiveDirectoryIterator */
|
|
|
|
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir_name));
|
|
|
|
$iterator->rewind();
|
|
|
|
|
|
|
|
$diff_files = [];
|
|
|
|
|
|
|
|
while ($iterator->valid()) {
|
|
|
|
if (!$iterator->isDot()) {
|
|
|
|
$extension = $iterator->getExtension();
|
|
|
|
if (in_array($extension, $file_extensions)) {
|
2016-10-15 06:12:57 +02:00
|
|
|
$file_name = (string)$iterator->getRealPath();
|
2016-10-07 06:58:08 +02:00
|
|
|
|
|
|
|
if (FileChecker::hasFileChanged($file_name)) {
|
|
|
|
$diff_files[] = $file_name;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$iterator->next();
|
|
|
|
}
|
|
|
|
|
|
|
|
return $diff_files;
|
|
|
|
}
|
|
|
|
|
2016-10-15 06:12:57 +02:00
|
|
|
/**
|
|
|
|
* @param Config $config
|
|
|
|
* @param bool $debug
|
2016-11-04 01:51:56 +01:00
|
|
|
* @param array<string> $file_list
|
2016-10-15 06:12:57 +02:00
|
|
|
* @return void
|
|
|
|
*/
|
2016-12-08 04:38:57 +01:00
|
|
|
protected function checkDiffFilesWithConfig(Config $config, $debug, array $file_list = [])
|
2016-10-05 19:24:46 +02:00
|
|
|
{
|
|
|
|
$file_extensions = $config->getFileExtensions();
|
|
|
|
$filetype_handlers = $config->getFiletypeHandlers();
|
|
|
|
|
|
|
|
foreach ($file_list as $file_name) {
|
2016-10-09 02:49:14 +02:00
|
|
|
if (!file_exists($file_name)) {
|
|
|
|
continue;
|
|
|
|
}
|
2016-10-18 16:17:25 +02:00
|
|
|
|
2016-11-02 07:29:00 +01:00
|
|
|
if (!$config->isInProjectDirs(
|
|
|
|
preg_replace('/^' . preg_quote($config->getBaseDir(), '/') . '/', '', $file_name)
|
|
|
|
)) {
|
2016-10-18 16:17:25 +02:00
|
|
|
if ($debug) {
|
|
|
|
echo('skipping ' . $file_name . PHP_EOL);
|
|
|
|
}
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
2016-10-09 02:49:14 +02:00
|
|
|
|
2016-10-05 19:24:46 +02:00
|
|
|
$extension = pathinfo($file_name, PATHINFO_EXTENSION);
|
|
|
|
|
|
|
|
if ($debug) {
|
|
|
|
echo 'Checking affected file ' . $file_name . PHP_EOL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isset($filetype_handlers[$extension])) {
|
|
|
|
/** @var FileChecker */
|
|
|
|
$file_checker = new $filetype_handlers[$extension]($file_name);
|
2016-11-02 07:29:00 +01:00
|
|
|
} else {
|
2016-10-05 19:24:46 +02:00
|
|
|
$file_checker = new FileChecker($file_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
$file_checker->check(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-15 06:12:57 +02:00
|
|
|
/**
|
|
|
|
* @param string $file_name
|
2016-11-13 17:24:46 +01:00
|
|
|
* @param bool $debug
|
|
|
|
* @param bool $update_docblocks
|
2016-10-15 06:12:57 +02:00
|
|
|
* @return void
|
|
|
|
*/
|
2016-12-08 04:38:57 +01:00
|
|
|
public function checkFile($file_name, $debug = false, $update_docblocks = false)
|
2016-06-20 06:38:13 +02:00
|
|
|
{
|
|
|
|
if ($debug) {
|
|
|
|
echo 'Checking ' . $file_name . PHP_EOL;
|
|
|
|
}
|
2016-06-10 00:08:25 +02:00
|
|
|
|
2016-12-08 04:38:57 +01:00
|
|
|
if (!$this->config) {
|
|
|
|
$this->config = self::getConfigForPath($file_name);
|
2016-06-26 19:45:20 +02:00
|
|
|
}
|
2016-06-20 06:38:13 +02:00
|
|
|
|
2016-12-08 04:38:57 +01:00
|
|
|
$this->config->hide_external_errors = $this->config->isInProjectDirs(
|
|
|
|
$this->config->shortenFileName($file_name)
|
2016-11-02 07:29:00 +01:00
|
|
|
);
|
2016-09-01 05:12:35 +02:00
|
|
|
|
2016-07-26 21:00:40 +02:00
|
|
|
$file_name_parts = explode('.', $file_name);
|
|
|
|
|
|
|
|
$extension = array_pop($file_name_parts);
|
2016-06-20 06:38:13 +02:00
|
|
|
|
2016-12-08 04:38:57 +01:00
|
|
|
$filetype_handlers = $this->config->getFiletypeHandlers();
|
2016-06-20 06:38:13 +02:00
|
|
|
|
2016-10-05 19:24:46 +02:00
|
|
|
FileChecker::loadReferenceCache();
|
|
|
|
|
2016-06-20 06:38:13 +02:00
|
|
|
if (isset($filetype_handlers[$extension])) {
|
|
|
|
/** @var FileChecker */
|
2016-06-28 20:28:45 +02:00
|
|
|
$file_checker = new $filetype_handlers[$extension]($file_name);
|
2016-11-02 07:29:00 +01:00
|
|
|
} else {
|
2016-06-28 20:28:45 +02:00
|
|
|
$file_checker = new FileChecker($file_name);
|
2016-06-10 00:08:25 +02:00
|
|
|
}
|
2016-06-20 06:38:13 +02:00
|
|
|
|
2016-11-13 00:51:48 +01:00
|
|
|
$file_checker->check(true, true, null, true, $update_docblocks);
|
2016-06-21 01:30:38 +02:00
|
|
|
|
2016-06-26 21:18:40 +02:00
|
|
|
IssueBuffer::finish();
|
2016-06-10 00:08:25 +02:00
|
|
|
}
|
2016-06-26 19:45:20 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets a Config object from an XML file.
|
2016-11-02 07:29:00 +01:00
|
|
|
*
|
|
|
|
* Searches up a folder hierarchy for the most immediate config.
|
2016-06-26 19:45:20 +02:00
|
|
|
*
|
|
|
|
* @param string $path
|
|
|
|
* @return Config
|
2016-11-02 07:29:00 +01:00
|
|
|
* @throws Exception\ConfigException If a config path is not found.
|
2016-06-26 19:45:20 +02:00
|
|
|
*/
|
|
|
|
protected static function getConfigForPath($path)
|
|
|
|
{
|
|
|
|
$dir_path = realpath($path) . '/';
|
|
|
|
|
|
|
|
if (!is_dir($dir_path)) {
|
|
|
|
$dir_path = dirname($dir_path) . '/';
|
|
|
|
}
|
|
|
|
|
|
|
|
$config = null;
|
|
|
|
|
|
|
|
do {
|
|
|
|
$maybe_path = $dir_path . Config::DEFAULT_FILE_NAME;
|
|
|
|
|
|
|
|
if (file_exists($maybe_path)) {
|
2016-12-29 16:24:10 +01:00
|
|
|
$config = Config::loadFromXMLFile($maybe_path);
|
2016-07-26 21:03:15 +02:00
|
|
|
|
|
|
|
if ($config->autoloader) {
|
|
|
|
require_once($dir_path . $config->autoloader);
|
|
|
|
}
|
|
|
|
|
2016-11-21 03:49:06 +01:00
|
|
|
$config->collectPredefinedConstants();
|
|
|
|
|
2016-06-26 19:45:20 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
$dir_path = preg_replace('/[^\/]+\/$/', '', $dir_path);
|
2016-11-02 07:29:00 +01:00
|
|
|
} while ($dir_path !== '/');
|
2016-06-26 19:45:20 +02:00
|
|
|
|
|
|
|
if (!$config) {
|
|
|
|
throw new Exception\ConfigException('Config not found for path ' . $path);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $config;
|
|
|
|
}
|
2016-06-26 21:33:51 +02:00
|
|
|
|
2016-10-15 06:12:57 +02:00
|
|
|
/**
|
|
|
|
* @param string $path_to_config
|
2016-11-02 07:29:00 +01:00
|
|
|
* @return void
|
|
|
|
* @throws Exception\ConfigException If a config file is not found in the given location.
|
2016-10-15 06:12:57 +02:00
|
|
|
*/
|
2016-12-08 04:38:57 +01:00
|
|
|
public function setConfigXML($path_to_config)
|
2016-06-26 21:33:51 +02:00
|
|
|
{
|
|
|
|
if (!file_exists($path_to_config)) {
|
|
|
|
throw new Exception\ConfigException('Config not found at location ' . $path_to_config);
|
|
|
|
}
|
|
|
|
|
2016-07-26 21:00:40 +02:00
|
|
|
$dir_path = dirname($path_to_config) . '/';
|
|
|
|
|
2016-12-29 16:24:10 +01:00
|
|
|
$this->config = Config::loadFromXMLFile($path_to_config);
|
2016-07-26 21:00:40 +02:00
|
|
|
|
2016-12-08 04:38:57 +01:00
|
|
|
if ($this->config->autoloader) {
|
|
|
|
require_once($dir_path . $this->config->autoloader);
|
2016-07-26 21:03:15 +02:00
|
|
|
}
|
2016-11-21 03:49:06 +01:00
|
|
|
|
2016-12-08 04:38:57 +01:00
|
|
|
$this->config->collectPredefinedConstants();
|
2016-06-26 21:33:51 +02:00
|
|
|
}
|
2016-10-05 19:24:46 +02:00
|
|
|
|
2016-10-15 06:12:57 +02:00
|
|
|
/**
|
|
|
|
* @param array<string> $diff_files
|
|
|
|
* @return array<string>
|
|
|
|
*/
|
2016-10-05 19:24:46 +02:00
|
|
|
public static function getReferencedFilesFromDiff(array $diff_files)
|
|
|
|
{
|
2016-10-05 23:08:20 +02:00
|
|
|
$all_inherited_files_to_check = $diff_files;
|
2016-10-05 19:24:46 +02:00
|
|
|
|
|
|
|
while ($diff_files) {
|
|
|
|
$diff_file = array_shift($diff_files);
|
|
|
|
|
2016-10-05 23:08:20 +02:00
|
|
|
$dependent_files = FileChecker::getFilesInheritingFromFile($diff_file);
|
|
|
|
$new_dependent_files = array_diff($dependent_files, $all_inherited_files_to_check);
|
|
|
|
|
|
|
|
$all_inherited_files_to_check += $new_dependent_files;
|
|
|
|
$diff_files += $new_dependent_files;
|
|
|
|
}
|
|
|
|
|
|
|
|
$all_files_to_check = $all_inherited_files_to_check;
|
|
|
|
|
|
|
|
foreach ($all_inherited_files_to_check as $file_name) {
|
|
|
|
$dependent_files = FileChecker::getFilesReferencingFile($file_name);
|
|
|
|
$all_files_to_check = array_merge($dependent_files, $all_files_to_check);
|
2016-10-05 19:24:46 +02:00
|
|
|
}
|
|
|
|
|
2016-10-05 23:08:20 +02:00
|
|
|
return array_unique($all_files_to_check);
|
2016-10-05 19:24:46 +02:00
|
|
|
}
|
2016-12-08 04:38:57 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @param string $file_path
|
|
|
|
* @param string $file_contents
|
|
|
|
* @return void
|
|
|
|
*/
|
|
|
|
public function registerFile($file_path, $file_contents)
|
|
|
|
{
|
|
|
|
$this->fake_files[$file_path] = $file_contents;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param string $file_path
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
public function getFileContents($file_path)
|
|
|
|
{
|
|
|
|
if (isset($this->fake_files[$file_path])) {
|
|
|
|
return $this->fake_files[$file_path];
|
|
|
|
}
|
|
|
|
|
|
|
|
return (string)file_get_contents($file_path);
|
|
|
|
}
|
2016-06-10 00:08:25 +02:00
|
|
|
}
|