ArcanistLintSeverity::SEVERITY_ERROR ); } public function getLintNameMap() { return array( self::JSHINT_ERROR => "JSHint Error" ); } public function getJSHintOptions() { $working_copy = $this->getEngine()->getWorkingCopy(); $options = '--reporter '.dirname(realpath(__FILE__)).'/reporter.js'; $config = $working_copy->getConfig('lint.jshint.config'); if ($config !== null) { $config = Filesystem::resolvePath($config, $working_copy->getProjectRoot()); if (!Filesystem::pathExists($config)) { throw new ArcanistUsageException( "Unable to find custom options file defined by 'lint.jshint.config'. ". "Make sure that the path is correct."); } $options .= ' --config '.$config; } return $options; } private function getJSHintPath() { $working_copy = $this->getEngine()->getWorkingCopy(); $prefix = $working_copy->getConfig('lint.jshint.prefix'); $bin = $working_copy->getConfig('lint.jshint.bin'); if ($bin === null) { $bin = "jshint"; } if ($prefix !== null) { $bin = $prefix."/".$bin; if (!Filesystem::pathExists($bin)) { throw new ArcanistUsageException( "Unable to find JSHint binary in a specified directory. Make sure ". "that 'lint.jshint.prefix' and 'lint.jshint.bin' keys are set ". "correctly. If you'd rather use a copy of JSHint installed globally, ". "you can just remove these keys from your .arcconfig"); } return $bin; } // Look for globally installed JSHint list($err) = exec_manual('which %s', $bin); if ($err) { throw new ArcanistUsageException( "JSHint does not appear to be installed on this system. Install it ". "(e.g., with 'npm install jshint -g') or configure ". "'lint.jshint.prefix' in your .arcconfig to point to the directory ". "where it resides."); } return $bin; } public function willLintPaths(array $paths) { $jshint_bin = $this->getJSHintPath(); $jshint_options = $this->getJSHintOptions(); $futures = array(); foreach ($paths as $path) { $filepath = $this->getEngine()->getFilePathOnDisk($path); $futures[$path] = new ExecFuture("{$jshint_bin} {$filepath} ${jshint_options}"); } foreach (Futures($futures)->limit(8) as $path => $future) { $this->results[$path] = $future->resolve(); } } public function lintPath($path) { list($rc, $stdout) = $this->results[$path]; if ($rc === 0) { return; } $errors = json_decode($stdout); if (!is_array($errors)) { // Something went wrong and we can't decode the output. Exit abnormally. throw new ArcanistUsageException( "JSHint returned output we can't parse. Check that your JSHint installation.\n". "Output:\n". $stdout); } foreach ($errors as $err) { $this->raiseLintAtLine( $err->line, $err->col, self::JSHINT_ERROR, $err->reason); } } }