Skip to content

Commit

Permalink
jscomp: allow using AbstractCommandLineRunner.exitCodeHandler in non-…
Browse files Browse the repository at this point in the history
…test mode.

{Abstract,}CommandLineRunner do a lot of output wrangling including generating source line maps
which makes it a decent programmatic interface, especially when many flags are pass-through.

Doing work after it exits though is tough because run() calls System.exit.

This cleans up uses of System.err and System.exit so that local versions err,exitCodeHandler
are always used, and allows overriding exitCodeHandler in non-test mode.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=130312217
  • Loading branch information
msamuel authored and blickly committed Aug 15, 2016
1 parent eb5bc1e commit d359ff8
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 16 deletions.
52 changes: 39 additions & 13 deletions src/com/google/javascript/jscomp/AbstractCommandLineRunner.java
Expand Up @@ -191,7 +191,7 @@ public abstract class AbstractCommandLineRunner<A extends Compiler,
private Supplier<List<SourceFile>> externsSupplierForTesting = null;
private Supplier<List<SourceFile>> inputsSupplierForTesting = null;
private Supplier<List<JSModule>> modulesSupplierForTesting = null;
private Function<Integer, Boolean> exitCodeReceiverForTesting = null;
private Function<Integer, Void> exitCodeReceiver = SystemExitCodeReceiver.INSTANCE;
private Map<String, String> rootRelativePathsMap = null;

private Map<String, String> parsedModuleWrappers = null;
Expand Down Expand Up @@ -234,14 +234,22 @@ void enableTestMode(
Supplier<List<SourceFile>> externsSupplier,
Supplier<List<SourceFile>> inputsSupplier,
Supplier<List<JSModule>> modulesSupplier,
Function<Integer, Boolean> exitCodeReceiver) {
Function<Integer, Void> exitCodeReceiver) {
Preconditions.checkArgument(
inputsSupplier == null ^ modulesSupplier == null);
testMode = true;
this.externsSupplierForTesting = externsSupplier;
this.inputsSupplierForTesting = inputsSupplier;
this.modulesSupplierForTesting = modulesSupplier;
this.exitCodeReceiverForTesting = exitCodeReceiver;
this.exitCodeReceiver = exitCodeReceiver;
}

/**
* @param newExitCodeReceiver receives a non-zero integer to indicate a
* problem during execution or 0i to indicate success.
*/
public void setExitCodeReceiver(Function<Integer, Void> newExitCodeReceiver) {
this.exitCodeReceiver = Preconditions.checkNotNull(newExitCodeReceiver);
}

/**
Expand Down Expand Up @@ -540,25 +548,21 @@ public final void run() {
result = doRun();
}
} catch (AbstractCommandLineRunner.FlagUsageException e) {
System.err.println(e.getMessage());
err.println(e.getMessage());
result = -1;
} catch (Throwable t) {
t.printStackTrace();
t.printStackTrace(err);
result = -2;
}

if (testMode) {
exitCodeReceiverForTesting.apply(result);
} else {
System.exit(result);
}
exitCodeReceiver.apply(result);
}

/**
* Returns the PrintStream for writing errors associated with this
* AbstractCommandLineRunner.
*/
protected PrintStream getErrorPrintStream() {
protected final PrintStream getErrorPrintStream() {
return err;
}

Expand Down Expand Up @@ -1533,7 +1537,7 @@ private Writer fileNameToLegacyOutputWriter(String fileName)
if (fileName == null) {
return null;
}
if (testMode) {
if (isInTestMode()) {
return new StringWriter();
}

Expand All @@ -1548,7 +1552,7 @@ private Writer fileNameToOutputWriter2(String fileName) throws IOException {
if (fileName == null) {
return null;
}
if (testMode) {
if (isInTestMode()) {
return new StringWriter();
}

Expand Down Expand Up @@ -2734,4 +2738,26 @@ public int getNumJsFiles() {
return numJsFiles;
}
}


static final class SystemExitCodeReceiver implements Function<Integer, Void> {
static final SystemExitCodeReceiver INSTANCE = new SystemExitCodeReceiver();

private SystemExitCodeReceiver() {
// singleton
}

@Override
public Void apply(Integer exitCode) {
int exitCodeValue = Preconditions.checkNotNull(exitCode);
// Don't spuriously report success.
// Posix conventions only guarantee that 8b are significant.
byte exitCodeByte = (byte) exitCodeValue;
if (exitCodeByte == 0 && exitCodeValue != 0) {
exitCodeByte = (byte) -1;
}
System.exit(exitCodeByte);
return null;
}
}
}
7 changes: 4 additions & 3 deletions test/com/google/javascript/jscomp/CommandLineRunnerTest.java
Expand Up @@ -2201,10 +2201,11 @@ private Compiler compile(String[] original) {
Suppliers.ofInstance(externs),
inputsSupplier,
modulesSupplier,
new Function<Integer, Boolean>() {
new Function<Integer, Void>() {
@Override
public Boolean apply(Integer code) {
return exitCodes.add(code);
public Void apply(Integer code) {
exitCodes.add(code);
return null;
}
});
runner.run();
Expand Down

0 comments on commit d359ff8

Please sign in to comment.