public function willParseFiles(array $file_map) { $root = dirname(phutil_get_library_root('javelin-diviner')); $bin = $root . '/jsast/jsast'; if (!Filesystem::pathExists($bin)) { throw new Exception("You must build the 'jsast' binary before you can generate " . "Javelin documentation."); } $futures = array(); foreach ($file_map as $file => $data) { $future = new ExecFuture($bin); $future->write($data); $futures[$file] = $future; } foreach (Futures($futures)->limit(8) as $file => $future) { $this->trees[$file] = $future->resolveJSON(); } }
public function willLintPaths(array $paths) { if (!xhpast_is_available()) { throw new Exception(xhpast_get_build_instructions()); } // NOTE: For now, we completely ignore paths and just lint every library in // its entirety. This is simpler and relatively fast because we don't do any // detailed checks and all the data we need for this comes out of module // caches. $bootloader = PhutilBootloader::getInstance(); $libs = $bootloader->getAllLibraries(); // Load the up-to-date map for each library, without loading the library // itself. This means lint results will accurately reflect the state of // the working copy. $arc_root = dirname(phutil_get_library_root('arcanist')); $bin = "{$arc_root}/scripts/phutil_rebuild_map.php"; $symbols = array(); foreach ($libs as $lib) { // Do these one at a time since they individually fanout to saturate // available system resources. $future = new ExecFuture('%s --show --quiet --ugly -- %s', $bin, phutil_get_library_root($lib)); $symbols[$lib] = $future->resolveJSON(); } $all_symbols = array(); foreach ($symbols as $library => $map) { // Check for files which declare more than one class/interface in the same // file, or mix function definitions with class/interface definitions. We // must isolate autoloadable symbols to one per file so the autoloader // can't end up in an unresolvable cycle. foreach ($map as $file => $spec) { $have = idx($spec, 'have', array()); $have_classes = idx($have, 'class', array()) + idx($have, 'interface', array()); $have_functions = idx($have, 'function'); if ($have_functions && $have_classes) { $function_list = implode(', ', array_keys($have_functions)); $class_list = implode(', ', array_keys($have_classes)); $this->raiseLintInLibrary($library, $file, end($have_functions), self::LINT_ONE_CLASS_PER_FILE, "File '{$file}' mixes function ({$function_list}) and " . "class/interface ({$class_list}) definitions in the same file. " . "A file which declares a class or an interface MUST " . "declare nothing else."); } else { if (count($have_classes) > 1) { $class_list = implode(', ', array_keys($have_classes)); $this->raiseLintInLibrary($library, $file, end($have_classes), self::LINT_ONE_CLASS_PER_FILE, "File '{$file}' declares more than one class or interface " . "({$class_list}). A file which declares a class or interface MUST " . "declare nothing else."); } } } // Check for duplicate symbols: two files providing the same class or // function. foreach ($map as $file => $spec) { $have = idx($spec, 'have', array()); foreach (array('class', 'function', 'interface') as $type) { $libtype = $type == 'interface' ? 'class' : $type; foreach (idx($have, $type, array()) as $symbol => $offset) { if (empty($all_symbols[$libtype][$symbol])) { $all_symbols[$libtype][$symbol] = array('library' => $library, 'file' => $file, 'offset' => $offset); continue; } $osrc = $all_symbols[$libtype][$symbol]['file']; $olib = $all_symbols[$libtype][$symbol]['library']; $this->raiseLintInLibrary($library, $file, $offset, self::LINT_DUPLICATE_SYMBOL, "Definition of {$type} '{$symbol}' in '{$file}' in library " . "'{$library}' duplicates prior definition in '{$osrc}' in " . "library '{$olib}'."); } } } } foreach ($symbols as $library => $map) { // Check for unknown symbols: uses of classes, functions or interfaces // which are not defined anywhere. We reference the list of all symbols // we built up earlier. foreach ($map as $file => $spec) { $need = idx($spec, 'need', array()); foreach (array('class', 'function', 'interface') as $type) { $libtype = $type == 'interface' ? 'class' : $type; foreach (idx($need, $type, array()) as $symbol => $offset) { if (!empty($all_symbols[$libtype][$symbol])) { // Symbol is defined somewhere. continue; } $this->raiseLintInLibrary($library, $file, $offset, self::LINT_UNKNOWN_SYMBOL, "Use of unknown {$type} '{$symbol}'. This symbol is not defined " . "in any loaded phutil library."); } } } } }
public static function newFromArcBundle($path) { $path = Filesystem::resolvePath($path); $future = new ExecFuture('tar tfO %s', $path); list($stdout, $file_list) = $future->resolvex(); $file_list = explode("\n", trim($file_list)); if (in_array('meta.json', $file_list)) { $future = new ExecFuture('tar xfO %s meta.json', $path); $meta_info = $future->resolveJSON(); $version = idx($meta_info, 'version', 0); $project_name = idx($meta_info, 'projectName'); $base_revision = idx($meta_info, 'baseRevision'); $revision_id = idx($meta_info, 'revisionID'); $encoding = idx($meta_info, 'encoding'); $author_name = idx($meta_info, 'authorName'); $author_email = idx($meta_info, 'authorEmail'); } else { // this arc bundle was probably made before we started storing meta info $version = 0; $project_name = null; $base_revision = null; $revision_id = null; $encoding = null; $author = null; } $future = new ExecFuture('tar xfO %s changes.json', $path); $changes = $future->resolveJSON(); foreach ($changes as $change_key => $change) { foreach ($change['hunks'] as $key => $hunk) { list($hunk_data) = execx('tar xfO %s hunks/%s', $path, $hunk['corpus']); $changes[$change_key]['hunks'][$key]['corpus'] = $hunk_data; } } foreach ($changes as $change_key => $change) { $changes[$change_key] = ArcanistDiffChange::newFromDictionary($change); } $obj = new ArcanistBundle(); $obj->changes = $changes; $obj->diskPath = $path; $obj->setProjectID($project_name); $obj->setBaseRevision($base_revision); $obj->setRevisionID($revision_id); $obj->setEncoding($encoding); return $obj; }
private function liberateGetChangedPaths($path) { $mapper = $this->getPhutilMapperLocation(); $future = new ExecFuture('%s %s --find-paths-for-liberate', $mapper, $path); return $future->resolveJSON(); }