$argv */ public static function run(array $argv): void { gc_disable(); ErrorHandler::install(); $valid_short_options = [ 'h', 'v', 'c:', 'r:', ]; $valid_long_options = [ 'clear-cache', 'config:', 'find-dead-code', 'help', 'root:', 'use-ini-defaults', 'version', 'tcp:', 'tcp-server', 'disable-on-change::', 'enable-autocomplete::', 'use-extended-diagnostic-codes', 'verbose' ]; $args = array_slice($argv, 1); $psalm_proxy = array_search('--language-server', $args, true); if ($psalm_proxy !== false) { unset($args[$psalm_proxy]); } array_map( function (string $arg) use ($valid_long_options): void { if (strpos($arg, '--') === 0 && $arg !== '--') { $arg_name = preg_replace('/=.*$/', '', substr($arg, 2)); if (!in_array($arg_name, $valid_long_options, true) && !in_array($arg_name . ':', $valid_long_options, true) && !in_array($arg_name . '::', $valid_long_options, true) ) { fwrite( STDERR, 'Unrecognised argument "--' . $arg_name . '"' . PHP_EOL . 'Type --help to see a list of supported arguments' . PHP_EOL ); error_log('Bad argument'); exit(1); } } }, $args ); // get options from command line $options = getopt(implode('', $valid_short_options), $valid_long_options); if (!array_key_exists('use-ini-defaults', $options)) { ini_set('display_errors', '1'); ini_set('display_startup_errors', '1'); ini_set('memory_limit', (string) (8 * 1024 * 1024 * 1024)); } if (array_key_exists('help', $options)) { $options['h'] = false; } if (array_key_exists('version', $options)) { $options['v'] = false; } if (isset($options['config'])) { $options['c'] = $options['config']; } if (isset($options['c']) && is_array($options['c'])) { fwrite(STDERR, 'Too many config files provided' . PHP_EOL); exit(1); } if (array_key_exists('h', $options)) { echo <<runAndCollect( function () use ($current_dir, $options, $vendor_dir): ?ClassLoader { return CliUtils::requireAutoloaders($current_dir, isset($options['r']), $vendor_dir); } ); if (array_key_exists('v', $options)) { echo 'Psalm ' . PSALM_VERSION . PHP_EOL; exit; } $ini_handler = new PsalmRestarter('PSALM'); $ini_handler->disableExtension('grpc'); // If Xdebug is enabled, restart without it $ini_handler->check(); setlocale(LC_CTYPE, 'C'); $path_to_config = CliUtils::getPathToConfig($options); if (isset($options['tcp'])) { if (!is_string($options['tcp'])) { fwrite(STDERR, 'tcp url should be a string' . PHP_EOL); exit(1); } } $find_unused_code = isset($options['find-dead-code']) ? 'auto' : null; $config = CliUtils::initializeConfig( $path_to_config, $current_dir, Report::TYPE_CONSOLE, $first_autoloader ); $config->setIncludeCollector($include_collector); if ($config->resolve_from_config_file) { $current_dir = $config->base_dir; chdir($current_dir); } $config->setServerMode(); if (isset($options['clear-cache'])) { $cache_directory = $config->getCacheDirectory(); if ($cache_directory !== null) { Config::removeCacheDirectory($cache_directory); } echo 'Cache directory deleted' . PHP_EOL; exit; } $providers = new Providers( new FileProvider, new ParserCacheProvider($config), new FileStorageCacheProvider($config), new ClassLikeStorageCacheProvider($config), new FileReferenceCacheProvider($config), new ProjectCacheProvider(Composer::getLockFilePath($current_dir)) ); $project_analyzer = new ProjectAnalyzer( $config, $providers ); if ($config->find_unused_variables) { $project_analyzer->getCodebase()->reportUnusedVariables(); } if ($config->find_unused_code) { $find_unused_code = 'auto'; } if (isset($options['disable-on-change'])) { $project_analyzer->onchange_line_limit = (int) $options['disable-on-change']; } $project_analyzer->provide_completion = !isset($options['enable-autocomplete']) || !is_string($options['enable-autocomplete']) || strtolower($options['enable-autocomplete']) !== 'false'; if ($find_unused_code) { $project_analyzer->getCodebase()->reportUnusedCode($find_unused_code); } if (isset($options['use-extended-diagnostic-codes'])) { $project_analyzer->language_server_use_extended_diagnostic_codes = true; } if (isset($options['verbose'])) { $project_analyzer->language_server_verbose = true; } $project_analyzer->server($options['tcp'] ?? null, isset($options['tcp-server'])); } }