diff --git a/teavm-cli/src/main/java/org/teavm/cli/TeaVMRunner.java b/teavm-cli/src/main/java/org/teavm/cli/TeaVMRunner.java index 9ce31c34e..579033f7f 100644 --- a/teavm-cli/src/main/java/org/teavm/cli/TeaVMRunner.java +++ b/teavm-cli/src/main/java/org/teavm/cli/TeaVMRunner.java @@ -15,16 +15,24 @@ */ package org.teavm.cli; -import java.io.File; +import java.io.*; import org.apache.commons.cli.*; import org.teavm.tooling.RuntimeCopyOperation; import org.teavm.tooling.TeaVMTool; +import org.teavm.tooling.TeaVMToolException; +import org.teavm.vm.TeaVMPhase; +import org.teavm.vm.TeaVMProgressFeedback; +import org.teavm.vm.TeaVMProgressListener; /** * * @author Alexey Andreev */ public final class TeaVMRunner { + private static long startTime; + private static long phaseStartTime; + private static TeaVMPhase currentPhase; + private TeaVMRunner() { } @@ -78,6 +86,10 @@ public final class TeaVMRunner { .withDescription("Incremental build cache directory") .withLongOpt("cachedir") .create('c')); + options.addOption(OptionBuilder + .withDescription("Wait for command after compilation, in order to enable hot recompilation") + .withLongOpt("--wait") + .create('w')); if (args.length == 0) { printUsage(options); @@ -139,6 +151,7 @@ public final class TeaVMRunner { } else { tool.setCacheDirectory(new File(tool.getTargetDirectory(), "teavm-cache")); } + boolean interactive = commandLine.hasOption('w'); args = commandLine.getArgs(); if (args.length > 1) { System.err.println("Unexpected arguments"); @@ -149,16 +162,98 @@ public final class TeaVMRunner { } tool.setLog(new ConsoleTeaVMToolLog()); tool.getProperties().putAll(System.getProperties()); + tool.setProgressListener(progressListener); - try { - tool.generate(); - } catch (Exception e) { - e.printStackTrace(System.err); - System.exit(-2); + if (interactive) { + boolean quit = false; + BufferedReader reader; + try { + reader = new BufferedReader(new InputStreamReader(System.in, "UTF-8")); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + System.exit(-2); + return; + } + do { + try { + build(tool); + } catch (Exception e) { + e.printStackTrace(System.err); + } + System.out.println("Press enter to repeat or enter 'q' to quit"); + try { + String line = reader.readLine().trim(); + if (!line.isEmpty()) { + if (line.equals("q")) { + quit = true; + } else { + System.out.println("Unrecognized command"); + } + } + } catch (IOException e) { + e.printStackTrace(); + System.exit(-2); + } + } while (!quit); + } else { + try { + build(tool); + } catch (Exception e) { + e.printStackTrace(System.err); + System.exit(-2); + } + if (!tool.getProblemProvider().getSevereProblems().isEmpty()) { + System.exit(-2); + } } - if (!tool.getProblemProvider().getSevereProblems().isEmpty()) { - System.exit(-2); + } + + private static void build(TeaVMTool tool) throws TeaVMToolException { + currentPhase = null; + startTime = System.currentTimeMillis(); + phaseStartTime = System.currentTimeMillis(); + tool.generate(); + reportPhaseComplete(); + System.out.println("Build complete for " + ((System.currentTimeMillis() - startTime) / 1000.0) + " seconds"); + } + + private static TeaVMProgressListener progressListener = new TeaVMProgressListener() { + @Override + public TeaVMProgressFeedback progressReached(int progress) { + return TeaVMProgressFeedback.CONTINUE; } + @Override + public TeaVMProgressFeedback phaseStarted(TeaVMPhase phase, int count) { + if (currentPhase != phase) { + if (currentPhase != null) { + reportPhaseComplete(); + } + phaseStartTime = System.currentTimeMillis(); + switch (phase) { + case DEPENDENCY_CHECKING: + System.out.print("Finding methods to decompile..."); + break; + case LINKING: + System.out.print("Linking methods..."); + break; + case DEVIRTUALIZATION: + System.out.print("Applying devirtualization..."); + break; + case DECOMPILATION: + System.out.print("Decompiling..."); + break; + case RENDERING: + System.out.print("Generating output..."); + break; + } + currentPhase = phase; + } + return TeaVMProgressFeedback.CONTINUE; + } + }; + + private static void reportPhaseComplete() { + System.out.println(" complete for " + ((System.currentTimeMillis() - phaseStartTime) / 1000.0) + " seconds"); } private static void printUsage(Options options) {