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-06-13 21:33:18 +02:00
|
|
|
use RecursiveDirectoryIterator;
|
|
|
|
use RecursiveIteratorIterator;
|
|
|
|
|
2016-08-13 20:20:46 +02:00
|
|
|
use Psalm\Config;
|
|
|
|
use Psalm\IssueBuffer;
|
2016-08-14 01:44:24 +02:00
|
|
|
use Psalm\Exception;
|
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
|
|
|
|
* @var Config|null
|
|
|
|
*/
|
|
|
|
protected static $config;
|
|
|
|
|
2016-07-25 21:05:58 +02:00
|
|
|
/**
|
|
|
|
* Whether or not to use colors in error output
|
|
|
|
* @var boolean
|
|
|
|
*/
|
|
|
|
public static $use_color = true;
|
|
|
|
|
2016-08-04 20:38:43 +02:00
|
|
|
/**
|
|
|
|
* Whether or not to show informational messages
|
|
|
|
* @var boolean
|
|
|
|
*/
|
|
|
|
public static $show_info = true;
|
|
|
|
|
2016-06-10 00:08:25 +02:00
|
|
|
public static function check($debug = false)
|
2016-06-13 21:33:18 +02:00
|
|
|
{
|
2016-06-26 21:33:51 +02:00
|
|
|
if (!self::$config) {
|
|
|
|
self::$config = self::getConfigForPath(getcwd());
|
|
|
|
}
|
2016-06-26 19:45:20 +02:00
|
|
|
|
|
|
|
foreach (self::$config->getIncludeDirs() as $dir_name) {
|
2016-06-26 21:25:38 +02:00
|
|
|
self::checkDirWithConfig($dir_name, self::$config, $debug);
|
2016-06-13 21:33:18 +02:00
|
|
|
}
|
2016-06-21 01:30:38 +02:00
|
|
|
|
2016-06-26 21:18:40 +02:00
|
|
|
IssueBuffer::finish();
|
2016-06-13 21:33:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public static function checkDir($dir_name, $debug = false)
|
2016-06-10 00:08:25 +02:00
|
|
|
{
|
2016-06-26 19:45:20 +02:00
|
|
|
if (!self::$config) {
|
|
|
|
self::$config = self::getConfigForPath($dir_name);
|
|
|
|
}
|
2016-06-10 00:08:25 +02:00
|
|
|
|
2016-06-26 21:25:38 +02:00
|
|
|
self::checkDirWithConfig($dir_name, self::$config, $debug);
|
|
|
|
|
|
|
|
IssueBuffer::finish();
|
|
|
|
}
|
|
|
|
|
|
|
|
protected static function checkDirWithConfig($dir_name, Config $config, $debug)
|
|
|
|
{
|
|
|
|
$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();
|
|
|
|
|
|
|
|
$files = [];
|
|
|
|
|
|
|
|
while ($iterator->valid()) {
|
|
|
|
if (!$iterator->isDot()) {
|
2016-06-20 06:38:13 +02:00
|
|
|
$extension = $iterator->getExtension();
|
|
|
|
if (in_array($extension, $file_extensions)) {
|
|
|
|
$file_name = $iterator->getRealPath();
|
|
|
|
|
|
|
|
if ($debug) {
|
|
|
|
echo 'Checking ' . $file_name . PHP_EOL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isset($filetype_handlers[$extension])) {
|
|
|
|
/** @var FileChecker */
|
|
|
|
$file_checker = new $filetype_handlers[$extension]($file_name);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$file_checker = new FileChecker($file_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
$file_checker->check(true);
|
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-06-20 06:38:13 +02:00
|
|
|
public static function checkFile($file_name, $debug = false)
|
|
|
|
{
|
|
|
|
if ($debug) {
|
|
|
|
echo 'Checking ' . $file_name . PHP_EOL;
|
|
|
|
}
|
2016-06-10 00:08:25 +02:00
|
|
|
|
2016-06-26 19:45:20 +02:00
|
|
|
if (!self::$config) {
|
|
|
|
self::$config = self::getConfigForPath($file_name);
|
|
|
|
}
|
2016-06-20 06:38:13 +02:00
|
|
|
|
2016-09-01 05:12:35 +02:00
|
|
|
self::$config->hide_external_errors = self::$config->isInProjectDirs(self::$config->shortenFileName($file_name));
|
|
|
|
|
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-06-26 19:45:20 +02:00
|
|
|
$filetype_handlers = self::$config->getFiletypeHandlers();
|
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-06-20 06:38:13 +02: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
|
|
|
|
|
|
|
$file_checker->check(true);
|
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.
|
|
|
|
* Searches up a folder hierachy for the most immediate config.
|
|
|
|
*
|
|
|
|
* @param string $path
|
|
|
|
* @return Config
|
|
|
|
*/
|
|
|
|
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-07-26 00:37:44 +02:00
|
|
|
$config = \Psalm\Config::loadFromXML($maybe_path);
|
2016-07-26 21:03:15 +02:00
|
|
|
|
|
|
|
if ($config->autoloader) {
|
|
|
|
require_once($dir_path . $config->autoloader);
|
|
|
|
}
|
|
|
|
|
2016-06-26 19:45:20 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
$dir_path = preg_replace('/[^\/]+\/$/', '', $dir_path);
|
|
|
|
}
|
|
|
|
while ($dir_path !== '/');
|
|
|
|
|
|
|
|
if (!$config) {
|
|
|
|
throw new Exception\ConfigException('Config not found for path ' . $path);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $config;
|
|
|
|
}
|
2016-06-26 21:33:51 +02:00
|
|
|
|
|
|
|
public static function setConfigXML($path_to_config)
|
|
|
|
{
|
|
|
|
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-07-26 00:37:44 +02:00
|
|
|
self::$config = \Psalm\Config::loadFromXML($path_to_config);
|
2016-07-26 21:00:40 +02:00
|
|
|
|
2016-07-26 21:03:15 +02:00
|
|
|
if (self::$config->autoloader) {
|
|
|
|
require_once($dir_path . self::$config->autoloader);
|
|
|
|
}
|
2016-06-26 21:33:51 +02:00
|
|
|
}
|
2016-06-10 00:08:25 +02:00
|
|
|
}
|