#!/usr/bin/env php \n"; exit(1); } phutil_require_module('phutil', 'filesystem'); phutil_require_module('phutil', 'future/exec'); $root = Filesystem::resolvePath($argv[1]); if (!@file_exists($root.'/__phutil_library_init__.php')) { throw new Exception("Provided path is not a phutil library."); } echo "Finding phutil modules...\n"; list($stdout) = execx( "(cd %s && find . -type d -path '*/.*' -prune -o -type d -print0)", $root); $futures = array(); foreach (array_filter(explode("\0", $stdout)) as $dir) { if ($dir == '.') { continue; } $module = preg_replace('@^\\./@', '', $dir); $futures[$module] = new ExecFuture( '%s %s', dirname(__FILE__).'/phutil_analyzer.php', $root.'/'.$module); } echo "Analyzing ".number_format(count($futures))." modules"; $class_map = array(); $requires_class_map = array(); $requires_interface_map = array(); $function_map = array(); foreach (Futures($futures)->limit(16) as $module => $future) { echo "."; $spec = $future->resolveJSON(); foreach (array('class', 'interface') as $type) { foreach ($spec['declares'][$type] as $class => $where) { if (!empty($class_map[$class])) { $prior = $class_map[$class]; echo "\n"; echo "Error: definition of {$type} '{$class}' in module '{$module}' ". "duplicates prior definition in module '{$prior}'."; echo "\n"; exit(1); } $class_map[$class] = $module; } } if (!empty($spec['chain']['class'])) { $requires_class_map += $spec['chain']['class']; } if (!empty($spec['chain']['interface'])) { $requires_interface_map += $spec['chain']['interface']; } foreach ($spec['declares']['function'] as $function => $where) { if (!empty($function_map[$function])) { $prior = $function_map[$function]; echo "\n"; echo "Error: definition of function '{$function}' in module '{$module}' ". "duplicates prior definition in module '{$prior}'."; echo "\n"; exit(1); } $function_map[$function] = $module; } } echo "\n"; ksort($class_map); ksort($requires_class_map); ksort($requires_interface_map); ksort($function_map); $library_map = array( 'class' => $class_map, 'function' => $function_map, 'requires_class' => $requires_class_map, 'requires_interface' => $requires_interface_map, ); $library_map = var_export($library_map, $return_string = true); $library_map = preg_replace('/\s+$/m', '', $library_map); $library_map = preg_replace('/array \(/', 'array(', $library_map); $at = '@'; $map_file = <<