package com.jscs.cli; import com.google.common.base.Charsets; import com.intellij.execution.ExecutionException; import com.intellij.execution.configurations.GeneralCommandLine; import com.intellij.execution.process.*; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.text.StringUtil; import com.jscs.cli.data.JscsLint; import com.jscs.cli.data.LintResult; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; import java.util.concurrent.TimeUnit; public final class JscsRunner { private JscsRunner() { } private static final Logger LOG = Logger.getInstance(JscsRunner.class); private static final int TIME_OUT = (int) TimeUnit.SECONDS.toMillis(120L); private static final String FIX = "--fix"; private static final String VERSION = "--fix"; // @NotNull // private static ProcessOutput runLint(@NotNull JscsSettings settings) throws ExecutionException { // GeneralCommandLine commandLine = createCommandLineLint(settings); // return execute(commandLine, TIME_OUT); // } public static LintResult lint(@NotNull String cwd, @NotNull String path, @NotNull String nodeInterpreter, @NotNull String jscsBin, @Nullable String jscsrc, @Nullable String preset, boolean esnext, String esprima) { JscsSettings settings = JscsSettings.build(cwd, path, nodeInterpreter, jscsBin, jscsrc, preset, esprima, esnext); return lint(settings); } public static LintResult lint(@NotNull JscsSettings settings) { LintResult result = new LintResult(); try { GeneralCommandLine commandLine = createCommandLineLint(settings); ProcessOutput out = execute(commandLine, TIME_OUT); // if (out.getExitCode() == 0) { // } else { result.errorOutput = out.getStderr(); try { result.jscsLint = JscsLint.read(out.getStdout()); } catch (Exception e) { //result.errorOutput = out.getStdout(); } // } } catch (Exception e) { e.printStackTrace(); result.errorOutput = e.toString(); } return result; } public static LintResult fix(@NotNull String cwd, @NotNull String path, @NotNull String nodeInterpreter, @NotNull String jscsBin, @Nullable String jscsrc, @Nullable String preset, boolean esnext, String esprima) { JscsSettings settings = JscsSettings.build(cwd, path, nodeInterpreter, jscsBin, jscsrc, preset, esprima, esnext); return fix(settings); } public static LintResult fix(@NotNull JscsSettings settings) { LintResult result = new LintResult(); try { GeneralCommandLine commandLine = createCommandLineLint(settings); commandLine.addParameter("--fix"); ProcessOutput out = execute(commandLine, TIME_OUT); result.errorOutput = out.getStderr(); try { result.jscsLint = JscsLint.read(out.getStdout()); } catch (Exception e) { LOG.error(e); //result.errorOutput = out.getStdout(); } } catch (Exception e) { e.printStackTrace(); result.errorOutput = e.toString(); } return result; } @NotNull private static ProcessOutput runVersion(@NotNull JscsSettings settings) throws ExecutionException { GeneralCommandLine commandLine = createCommandLine(settings); commandLine.addParameter("--version"); return execute(commandLine, TIME_OUT); } @NotNull public static String version(@NotNull JscsSettings settings) throws ExecutionException { if (!new File(settings.jscsExecutablePath).exists()) { LOG.warn("Calling version with invalid jscs exe " + settings.jscsExecutablePath); return ""; } ProcessOutput out = runVersion(settings); if (out.getExitCode() == 0) { return out.getStdout().trim(); } return ""; } @NotNull private static GeneralCommandLine createCommandLine(@NotNull JscsSettings settings) { GeneralCommandLine commandLine = new GeneralCommandLine(); commandLine.setWorkDirectory(settings.cwd); if (SystemInfo.isWindows) { commandLine.setExePath(settings.jscsExecutablePath); } else { commandLine.setExePath(settings.node); commandLine.addParameter(settings.jscsExecutablePath); } return commandLine; } @NotNull private static GeneralCommandLine createCommandLineLint(@NotNull JscsSettings settings) { GeneralCommandLine commandLine = createCommandLine(settings); // TODO validate arguments (file exist etc) commandLine.addParameter(settings.targetFile); addParamIfExist(commandLine, "config", settings.config); addParam(commandLine, "reporter", "checkstyle"); commandLine.addParameter("-v"); addParamIfExist(commandLine, "preset", settings.preset); addParamIfExist(commandLine, "esprima", settings.esprima); if (settings.esnext) { commandLine.addParameter("--esnext"); } return commandLine; } private static void addParam(GeneralCommandLine commandLine, String name, String value) { commandLine.addParameter("--" + name + '=' + value); } private static void addParamIfExist(GeneralCommandLine commandLine, String name, String value) { if (StringUtil.isNotEmpty(value)) { addParam(commandLine, name, value); } } @NotNull private static ProcessOutput execute(@NotNull GeneralCommandLine commandLine, int timeoutInMilliseconds) throws ExecutionException { LOG.info("Running jscs command: " + commandLine.getCommandLineString()); Process process = commandLine.createProcess(); OSProcessHandler processHandler = new ColoredProcessHandler(process, commandLine.getCommandLineString(), Charsets.UTF_8); final ProcessOutput output = new ProcessOutput(); processHandler.addProcessListener(new ProcessAdapter() { public void onTextAvailable(ProcessEvent event, Key outputType) { if (outputType.equals(ProcessOutputTypes.STDERR)) { output.appendStderr(event.getText()); } else if (!outputType.equals(ProcessOutputTypes.SYSTEM)) { output.appendStdout(event.getText()); } } }); processHandler.startNotify(); if (processHandler.waitFor(timeoutInMilliseconds)) { output.setExitCode(process.exitValue()); } else { processHandler.destroyProcess(); output.setTimeout(); } if (output.isTimeout()) { throw new ExecutionException("Command '" + commandLine.getCommandLineString() + "' is timed out."); } return output; } }