Making compiler exit codes type safe. Fixes the problem with wrong command-line argument usage being missed by the IDE
This commit is contained in:
@@ -23,6 +23,8 @@ import org.jetbrains.jet.compiler.MessageRenderer;
|
|||||||
|
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
|
|
||||||
|
import static org.jetbrains.jet.cli.KotlinCompiler.ExitCode.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author yole
|
* @author yole
|
||||||
* @author alex.tkachman
|
* @author alex.tkachman
|
||||||
@@ -30,6 +32,22 @@ import java.io.PrintStream;
|
|||||||
@SuppressWarnings("UseOfSystemOutOrSystemErr")
|
@SuppressWarnings("UseOfSystemOutOrSystemErr")
|
||||||
public class KotlinCompiler {
|
public class KotlinCompiler {
|
||||||
|
|
||||||
|
public enum ExitCode {
|
||||||
|
OK(0),
|
||||||
|
COMPILATION_ERROR(1),
|
||||||
|
INTERNAL_ERROR(2);
|
||||||
|
|
||||||
|
private final int code;
|
||||||
|
|
||||||
|
private ExitCode(int code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void main(String... args) {
|
public static void main(String... args) {
|
||||||
doMain(new KotlinCompiler(), args);
|
doMain(new KotlinCompiler(), args);
|
||||||
}
|
}
|
||||||
@@ -39,25 +57,25 @@ public class KotlinCompiler {
|
|||||||
*/
|
*/
|
||||||
public static void doMain(KotlinCompiler compiler, String[] args) {
|
public static void doMain(KotlinCompiler compiler, String[] args) {
|
||||||
try {
|
try {
|
||||||
int rc = compiler.exec(args);
|
ExitCode rc = compiler.exec(args);
|
||||||
if (rc != 0) {
|
if (rc != OK) {
|
||||||
System.err.println("exec() finished with " + rc + " return code");
|
System.err.println("exec() finished with " + rc + " return code");
|
||||||
System.exit(rc);
|
System.exit(rc.getCode());
|
||||||
}
|
}
|
||||||
} catch (CompileEnvironmentException e) {
|
} catch (CompileEnvironmentException e) {
|
||||||
System.err.println(e.getMessage());
|
System.err.println(e.getMessage());
|
||||||
System.exit(1);
|
System.exit(INTERNAL_ERROR.getCode());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int exec(String... args) {
|
public ExitCode exec(String... args) {
|
||||||
return exec(System.out, args);
|
return exec(System.out, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int exec(PrintStream errStream, String... args) {
|
public ExitCode exec(PrintStream errStream, String... args) {
|
||||||
CompilerArguments arguments = createArguments();
|
CompilerArguments arguments = createArguments();
|
||||||
if (!parseArguments(errStream, arguments, args)) {
|
if (!parseArguments(errStream, arguments, args)) {
|
||||||
return 1;
|
return INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
return exec(errStream, arguments);
|
return exec(errStream, arguments);
|
||||||
}
|
}
|
||||||
@@ -65,10 +83,10 @@ public class KotlinCompiler {
|
|||||||
/**
|
/**
|
||||||
* Executes the compiler on the parsed arguments
|
* Executes the compiler on the parsed arguments
|
||||||
*/
|
*/
|
||||||
public int exec(PrintStream errStream, CompilerArguments arguments) {
|
public ExitCode exec(PrintStream errStream, CompilerArguments arguments) {
|
||||||
if (arguments.help) {
|
if (arguments.help) {
|
||||||
usage(errStream);
|
usage(errStream);
|
||||||
return 0;
|
return OK;
|
||||||
}
|
}
|
||||||
System.setProperty("java.awt.headless", "true");
|
System.setProperty("java.awt.headless", "true");
|
||||||
|
|
||||||
@@ -84,11 +102,11 @@ public class KotlinCompiler {
|
|||||||
else {
|
else {
|
||||||
noErrors = environment.compileBunchOfSources(arguments.src, arguments.jar, arguments.outputDir, arguments.includeRuntime);
|
noErrors = environment.compileBunchOfSources(arguments.src, arguments.jar, arguments.outputDir, arguments.includeRuntime);
|
||||||
}
|
}
|
||||||
return noErrors ? 0 : 1;
|
return noErrors ? OK : COMPILATION_ERROR;
|
||||||
}
|
}
|
||||||
catch (Throwable t) {
|
catch (Throwable t) {
|
||||||
errStream.println(messageRenderer.renderException(t));
|
errStream.println(messageRenderer.renderException(t));
|
||||||
return 1;
|
return INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
environment.dispose();
|
environment.dispose();
|
||||||
@@ -104,7 +122,7 @@ public class KotlinCompiler {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException e) {
|
catch (IllegalArgumentException e) {
|
||||||
usage(System.err);
|
usage(errStream);
|
||||||
}
|
}
|
||||||
catch (Throwable t) {
|
catch (Throwable t) {
|
||||||
// Always use tags
|
// Always use tags
|
||||||
|
|||||||
@@ -55,10 +55,10 @@ public class CompileEnvironmentTest extends TestCase {
|
|||||||
try {
|
try {
|
||||||
File stdlib = ForTestCompileStdlib.stdlibJarForTests();
|
File stdlib = ForTestCompileStdlib.stdlibJarForTests();
|
||||||
File resultJar = new File(tempDir, "result.jar");
|
File resultJar = new File(tempDir, "result.jar");
|
||||||
int rv = new KotlinCompiler().exec("-module", JetParsingTest.getTestDataDir() + "/compiler/smoke/Smoke.kts",
|
KotlinCompiler.ExitCode rv = new KotlinCompiler().exec("-module", JetParsingTest.getTestDataDir() + "/compiler/smoke/Smoke.kts",
|
||||||
"-jar", resultJar.getAbsolutePath(),
|
"-jar", resultJar.getAbsolutePath(),
|
||||||
"-stdlib", stdlib.getAbsolutePath());
|
"-stdlib", stdlib.getAbsolutePath());
|
||||||
Assert.assertEquals("compilation completed with non-zero code", 0, rv);
|
Assert.assertEquals("compilation completed with non-zero code", KotlinCompiler.ExitCode.OK, rv);
|
||||||
FileInputStream fileInputStream = new FileInputStream(resultJar);
|
FileInputStream fileInputStream = new FileInputStream(resultJar);
|
||||||
try {
|
try {
|
||||||
JarInputStream is = new JarInputStream(fileInputStream);
|
JarInputStream is = new JarInputStream(fileInputStream);
|
||||||
|
|||||||
@@ -274,8 +274,10 @@ public class JetCompiler implements TranslatingCompiler {
|
|||||||
context.addMessage(INFORMATION, "Invoking in-process compiler " + compilerClassName + " with arguments " + Arrays.asList(arguments), "", -1, -1);
|
context.addMessage(INFORMATION, "Invoking in-process compiler " + compilerClassName + " with arguments " + Arrays.asList(arguments), "", -1, -1);
|
||||||
|
|
||||||
Object rc = exec.invoke(kompiler.newInstance(), out, arguments);
|
Object rc = exec.invoke(kompiler.newInstance(), out, arguments);
|
||||||
if (rc instanceof Integer) {
|
// exec() returns a KotlinCompiler.ExitCode object, that class is not accessible here,
|
||||||
return ((Integer) rc).intValue();
|
// so we take it's contents through reflection
|
||||||
|
if ("org.jetbrains.jet.cli.KotlinCompiler.ExitCode".equals(rc.getClass().getCanonicalName())) {
|
||||||
|
return (Integer) rc.getClass().getMethod("getCode").invoke(rc);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new IllegalStateException("Unexpected return: " + rc);
|
throw new IllegalStateException("Unexpected return: " + rc);
|
||||||
|
|||||||
@@ -150,8 +150,8 @@ public class LibrariesTest extends PlatformTestCase {
|
|||||||
protected void setUp() throws Exception {
|
protected void setUp() throws Exception {
|
||||||
super.setUp();
|
super.setUp();
|
||||||
String libraryDir = FileUtil.getTempDirectory();
|
String libraryDir = FileUtil.getTempDirectory();
|
||||||
int compilerExec = new KotlinCompiler().exec("-src", TEST_DATA_PATH + "/library", "-output", libraryDir);
|
KotlinCompiler.ExitCode compilerExec = new KotlinCompiler().exec("-src", TEST_DATA_PATH + "/library", "-output", libraryDir);
|
||||||
assertEquals(0, compilerExec);
|
assertEquals(KotlinCompiler.ExitCode.OK, compilerExec);
|
||||||
myLibraryDir = LocalFileSystem.getInstance().findFileByPath(libraryDir);
|
myLibraryDir = LocalFileSystem.getInstance().findFileByPath(libraryDir);
|
||||||
assertNotNull(myLibraryDir);
|
assertNotNull(myLibraryDir);
|
||||||
|
|
||||||
@@ -168,4 +168,4 @@ public class LibrariesTest extends PlatformTestCase {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user