/** * Create and read command line arguments, configuring * \Phan\Config as a side effect. */ public function __construct() { global $argv; // file_put_contents('/tmp/file', implode("\n", $argv)); // Parse command line args $opts = getopt("f:m:o:c:haqbrpid:s:3:t::"); // Determine the root directory of the project from which // we root all relative paths passed in as args Config::get()->setProjectRootDirectory($opts['d'] ?? getcwd()); // Now that we have a root directory, attempt to read a // configuration file `.phan/config.php` if it exists $this->maybeReadConfigFile(); foreach ($opts ?? [] as $key => $value) { switch ($key) { case 'h': $this->usage(); break; case 'f': if (is_file($value) && is_readable($value)) { $this->file_list = file($value, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); } else { Log::err(Log::EFATAL, "Unable to open {$value}"); } break; case 'm': if (!in_array($value, ['text', 'codeclimate'])) { $this->usage("Unknown output mode: {$value}"); } Log::setOutputMode($value); break; case 'c': Config::get()->parent_constructor_required = explode(',', $value); break; case 'q': Config::get()->quick_mode = true; break; case 'b': Config::get()->backward_compatibility_checks = true; break; case 'p': Config::get()->progress_bar = true; break; case 'a': Config::get()->dump_ast = true; break; case 'o': Log::setFilename($value); break; case 'i': Log::setOutputMask(Log::getOutputMask() ^ Log::EUNDEF); break; case 't': Config::get()->emit_trace_id = true; break; case '3': Config::get()->exclude_analysis_directory_list = explode(',', $value); break; case 's': Config::get()->stored_state_file_path = $value; break; case 'r': Config::get()->reanalyze_file_list = true; break; case 'd': // We handle this flag before parsing options so // that we can get the project root directory to // base other config flags values on break; default: $this->usage("Unknown option '-{$key}'"); break; } } $pruneargv = array(); foreach ($opts ?? [] as $opt => $value) { foreach ($argv as $key => $chunk) { $regex = '/^' . (isset($opt[1]) ? '--' : '-') . $opt . '/'; if ($chunk == $value && $argv[$key - 1][0] == '-' || preg_match($regex, $chunk)) { array_push($pruneargv, $key); } } } while ($key = array_pop($pruneargv)) { unset($argv[$key]); } if (empty($this->file_list) && count($argv) < 2) { // Log::err(Log::EFATAL, "No files to analyze"); } foreach ($argv as $arg) { if ($arg[0] == '-') { $this->usage("Unknown option '{$arg}'"); } } $this->file_list = array_merge($this->file_list, array_slice($argv, 1)); }
/** * Create and read command line arguments, configuring * \Phan\Config as a side effect. */ public function __construct() { global $argv; // file_put_contents('/tmp/file', implode("\n", $argv)); // Parse command line args // still available: g,j,k,n,t,u,v,w,z $opts = getopt("f:m:o:c:aeqbrpid:s:3:y:l:xh::", ['fileset:', 'output-mode:', 'output:', 'parent-constructor-required:', 'expanded-dependency-list', 'dump-ast', 'quick', 'backward-compatibility-checks', 'reanalyze-file-list', 'progress-bar', 'ignore-undeclared', 'project-root-directory:', 'state-file:', 'exclude-directory-list:', 'minimum-severity:', 'directory:', 'dead-code-detection', 'help']); // Determine the root directory of the project from which // we root all relative paths passed in as args Config::get()->setProjectRootDirectory($opts['d'] ?? getcwd()); // Now that we have a root directory, attempt to read a // configuration file `.phan/config.php` if it exists $this->maybeReadConfigFile(); foreach ($opts ?? [] as $key => $value) { switch ($key) { case 'h': case 'help': $this->usage(); break; case 'f': case 'fileset': $file_list = is_array($value) ? $value : [$value]; foreach ($file_list as $file_name) { if (is_file($file_name) && is_readable($file_name)) { $this->file_list = array_merge($this->file_list, file($file_name, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES)); } else { error_log("Unable to read file {$file_name}"); } } break; case 'l': case 'directory': $directory_list = is_array($value) ? $value : [$value]; foreach ($directory_list as $directory_name) { $this->file_list = array_merge($this->file_list, $this->directoryNameToFileList($directory_name)); } break; case 'm': case 'output-mode': if (!in_array($value, ['text', 'codeclimate'])) { $this->usage("Unknown output mode: {$value}"); } Log::setOutputMode($value); break; case 'c': case 'parent-constructor-required': Config::get()->parent_constructor_required = explode(',', $value); break; case 'q': case 'quick': Config::get()->quick_mode = true; break; case 'b': case 'backward-compatibility-checks': Config::get()->backward_compatibility_checks = true; break; case 'p': case 'progress-bar': Config::get()->progress_bar = true; break; case 'a': case 'dump-ast': Config::get()->dump_ast = true; break; case 'e': case 'expanded-dependency-list': Config::get()->expanded_dependency_list = true; break; case 'o': case 'output': Log::setFilename($value); break; case 'i': case 'ignore-undeclared': Log::setOutputMask(Log::getOutputMask() ^ Issue::CATEGORY_UNDEFINED); break; case '3': case 'exclude-directory-list': Config::get()->exclude_analysis_directory_list = explode(',', $value); break; case 's': case 'state-file': Config::get()->stored_state_file_path = $value; break; case 'r': case 'reanalyze-file-list': Config::get()->reanalyze_file_list = true; break; case 'y': case 'minimum-severity': Config::get()->minimum_severity = $value; break; case 'd': case 'project-root-directory': // We handle this flag before parsing options so // that we can get the project root directory to // base other config flags values on break; case 'x': case 'dead-code-detection': Config::get()->dead_code_detection = true; break; default: $this->usage("Unknown option '-{$key}'"); break; } } $pruneargv = array(); foreach ($opts ?? [] as $opt => $value) { foreach ($argv as $key => $chunk) { $regex = '/^' . (isset($opt[1]) ? '--' : '-') . $opt . '/'; if ($chunk == $value && $argv[$key - 1][0] == '-' || preg_match($regex, $chunk)) { array_push($pruneargv, $key); } } } while ($key = array_pop($pruneargv)) { unset($argv[$key]); } foreach ($argv as $arg) { if ($arg[0] == '-') { $this->usage("Unknown option '{$arg}'"); } } // Merge in any remaining args on the CLI $this->file_list = array_merge($this->file_list, array_slice($argv, 1)); // Merge in any files given in the config $this->file_list = array_merge($this->file_list, Config::get()->file_list); // Merge in any directories given in the config foreach (Config::get()->directory_list as $directory_name) { $this->file_list = array_merge($this->file_list, $this->directoryNameToFileList($directory_name)); } }
/** * Create and read command line arguments, configuring * \Phan\Config as a side effect. */ public function __construct() { global $argv; // Parse command line args $opts = getopt("f:m:o:c:haqbrpis:3:t::"); foreach ($opts ?? [] as $key => $value) { switch ($key) { case 'h': $this->usage(); break; case 'f': if (is_file($value) && is_readable($value)) { $this->file_list = file($value, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); } else { Log::err(Log::EFATAL, "Unable to open {$value}"); } break; case 'm': if (!in_array($value, ['verbose', 'short', 'json', 'csv'])) { $this->usage("Unknown output mode: {$value}"); } Log::setOutputMode($value); break; case 'c': Config::get()->parent_constructor_required = explode(',', $value); break; case 'q': Config::get()->quick_mode = true; break; case 'b': Config::get()->backward_compatibility_checks = true; break; case 'p': Config::get()->progress_bar = true; break; case 'a': Config::get()->dump_ast = true; break; case 'o': Log::setFilename($value); break; case 'i': Log::setOutputMask(Log::getOutputMask() ^ Log::EUNDEF); break; case 't': Config::get()->emit_trace_id = true; break; case '3': Config::get()->third_party_directory_list = explode(',', $value); break; case 's': Config::get()->serialized_code_base_file = $value; break; case 'r': Config::get()->reanalyze_file_list = true; break; default: $this->usage("Unknown option '-{$key}'"); break; } } $pruneargv = array(); foreach ($opts ?? [] as $opt => $value) { foreach ($argv as $key => $chunk) { $regex = '/^' . (isset($opt[1]) ? '--' : '-') . $opt . '/'; if ($chunk == $value && $argv[$key - 1][0] == '-' || preg_match($regex, $chunk)) { array_push($pruneargv, $key); } } } while ($key = array_pop($pruneargv)) { unset($argv[$key]); } if (empty($this->file_list) && count($argv) < 2) { Log::err(Log::EFATAL, "No files to analyze"); } foreach ($argv as $arg) { if ($arg[0] == '-') { $this->usage("Unknown option '{$arg}'"); } } $this->file_list = array_merge($this->file_list, array_slice($argv, 1)); }