Closed barretg closed 6 months ago
It appears that programmatic compilation is ONLY available when running in a JDK, so this will require that DrJava be run in a JDK and not just a JRE, which is an acceptable requirement IMO, given that it's an IDE.
@ponderosaTX Could you post a quick rundown of relevant portions of the codebase to get us started in the right direction? Thanks.
EDIT: in OH he said "anything that mentions the word 'Compiler' is going to be relevant"
The primary directory we'll need to make changes in is: drjava/src/edu/rice/cs/drjava/model/compiler
We'll want to decide on an implementation that extends the CompilerInterface interface and figure out if we need to implement a new CompilerModel to switch to when using the programmatic compilation option.
We'll use the JavaCompiler interface (the user's compiler can be retrieved with JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
Source
Here's a bunch of examples using the library.
We'll probably need to figure out if we want to swap out the current DefaultCompilerModel for a new one, or if we can make our compilation method use the same interfaces that it expects.
We'll need to decide if we want this to be the only way to compile things or if we still want to support user supplied compilers.
As per in class: this will be the new ONLY way to compile in DrJava, so we can remove the compiler selection panel in drjava/src/edu/rice/cs/drjava/ui/CompilerErrorPanel.java
One concern I had: Will programmatic compilation be properly sandboxed if it's using the same instance that DJ itself is running on? What does it look like to do development on say DJ itself where the classes are the ones currently loaded. Will compiling shadow the currently loaded DJ files?
Since the DrJava build process is performed "externally" using ant rather than internally within DrJava, the compiler runs in a completely different JVM than DrJava does. Whatever instances (perhaps none) of DrJava are running when a new DrJava jar file is created using ant are invisible to the build process. In contrast, the DrJava compile command compiles Java code inside the main JVM running DrJava. In this context, shadowing is a major issue. Fortunately in this project, the shadowing issue should not arise.
javaxtools-compile-test now has a working implementation of the javax.tools compiler, but it has not yet been thoroughly tested
These 5 unit tests fail:
[junit] Testcase: testCompileFailsCorrectLineNumbers(edu.rice.cs.drjava.model.GlobalModelCompileErrorsTest): FAILED
[junit] location of first error should be between 20 and 29 inclusive (line 2), but was 32
[junit] junit.framework.AssertionFailedError: location of first error should be between 20 and 29 inclusive (line 2), but was 32
[junit] at edu.rice.cs.drjava.model.GlobalModelCompileErrorsTest.testCompileFailsCorrectLineNumbers(GlobalModelCompileErrorsTest.java:333)
[junit] Testcase: testCompileReferenceToNonPublicClass(edu.rice.cs.drjava.model.GlobalModelCompileSuccessOptionsTest): FAILED
[junit] compile failed: compiler error(s):
[junit] class edu.rice.cs.drjava.model.compiler.CompilerErrorModel:
[junit] class edu.rice.cs.drjava.model.DJError(file=/private/var/folders/_t/972y5m553734blw13cl454bh0000gn/T/DrJava-test-barretglass121171146380553545/DrJava-test14695112214253015905.java, line=1, col=30, msg=auxiliary class Foo in DrJava-test5769801320084761434.java should not be accessed from outside its own source file)
[junit]
[junit] junit.framework.AssertionFailedError: compile failed: compiler error(s):
[junit] class edu.rice.cs.drjava.model.compiler.CompilerErrorModel:
[junit] class edu.rice.cs.drjava.model.DJError(file=/private/var/folders/_t/972y5m553734blw13cl454bh0000gn/T/DrJava-test-barretglass121171146380553545/DrJava-test14695112214253015905.java, line=1, col=30, msg=auxiliary class Foo in DrJava-test5769801320084761434.java should not be accessed from outside its own source file)
[junit]
[junit] at edu.rice.cs.drjava.model.GlobalModelCompileSuccessOptionsTest.testCompileReferenceToNonPublicClass(GlobalModelCompileSuccessOptionsTest.java:74)
[junit] Testcase: testInteractionsCanSeeCompiledClasses(edu.rice.cs.drjava.model.GlobalModelOtherTest): FAILED
[junit] compile errors > 0 ? numErrors = 1 expected:<false> but was:<true>
[junit] junit.framework.AssertionFailedError: compile errors > 0 ? numErrors = 1 expected:<false> but was:<true>
[junit] at edu.rice.cs.drjava.model.GlobalModelTestCase.assertCompileErrorsPresent(GlobalModelTestCase.java:551)
[junit] at edu.rice.cs.drjava.model.GlobalModelTestCase.assertCompileErrorsPresent(GlobalModelTestCase.java:544)
[junit] at edu.rice.cs.drjava.model.GlobalModelTestCase.doCompile(GlobalModelTestCase.java:336)
[junit] at edu.rice.cs.drjava.model.GlobalModelOtherTest.testInteractionsCanSeeCompiledClasses(GlobalModelOtherTest.java:179)
[junit] Testcase: testVerifyErrorHandledCorrectly_NOJOIN(edu.rice.cs.drjava.model.junit.JUnitErrorModelTest): FAILED
[junit] compile failed: compiler error(s):
[junit] class edu.rice.cs.drjava.model.compiler.CompilerErrorModel:
[junit] class edu.rice.cs.drjava.model.DJError(file=/private/var/folders/_t/972y5m553734blw13cl454bh0000gn/T/DrJava-test-barretglass3007482003144796830/ABC2.java, line=1, col=1, msg=serializable class ABC has no definition of serialVersionUID)
[junit] class edu.rice.cs.drjava.model.DJError(file=/private/var/folders/_t/972y5m553734blw13cl454bh0000gn/T/DrJava-test-barretglass3007482003144796830/ABC2.java, line=1, col=28, msg=found raw type: java.util.ArrayList
[junit] missing type arguments for generic class java.util.ArrayList<E>)
[junit]
[junit] junit.framework.AssertionFailedError: compile failed: compiler error(s):
[junit] class edu.rice.cs.drjava.model.compiler.CompilerErrorModel:
[junit] class edu.rice.cs.drjava.model.DJError(file=/private/var/folders/_t/972y5m553734blw13cl454bh0000gn/T/DrJava-test-barretglass3007482003144796830/ABC2.java, line=1, col=1, msg=serializable class ABC has no definition of serialVersionUID)
[junit] class edu.rice.cs.drjava.model.DJError(file=/private/var/folders/_t/972y5m553734blw13cl454bh0000gn/T/DrJava-test-barretglass3007482003144796830/ABC2.java, line=1, col=28, msg=found raw type: java.util.ArrayList
[junit] missing type arguments for generic class java.util.ArrayList<E>)
[junit]
[junit] at edu.rice.cs.drjava.model.junit.JUnitErrorModelTest.testVerifyErrorHandledCorrectly_NOJOIN(JUnitErrorModelTest.java:271)
[junit] Testcase: testVerifyErrorHandledCorrectly_NOJOIN(edu.rice.cs.drjava.model.junit.JUnitErrorModelTest): FAILED
[junit] compile failed: compiler error(s):
[junit] class edu.rice.cs.drjava.model.compiler.CompilerErrorModel:
[junit] class edu.rice.cs.drjava.model.DJError(file=/private/var/folders/_t/972y5m553734blw13cl454bh0000gn/T/DrJava-test-barretglass3007482003144796830/ABC2.java, line=1, col=1, msg=serializable class ABC has no definition of serialVersionUID)
[junit] class edu.rice.cs.drjava.model.DJError(file=/private/var/folders/_t/972y5m553734blw13cl454bh0000gn/T/DrJava-test-barretglass3007482003144796830/ABC2.java, line=1, col=28, msg=found raw type: java.util.ArrayList
[junit] missing type arguments for generic class java.util.ArrayList<E>)
[junit]
[junit] junit.framework.AssertionFailedError: compile failed: compiler error(s):
[junit] class edu.rice.cs.drjava.model.compiler.CompilerErrorModel:
[junit] class edu.rice.cs.drjava.model.DJError(file=/private/var/folders/_t/972y5m553734blw13cl454bh0000gn/T/DrJava-test-barretglass3007482003144796830/ABC2.java, line=1, col=1, msg=serializable class ABC has no definition of serialVersionUID)
[junit] class edu.rice.cs.drjava.model.DJError(file=/private/var/folders/_t/972y5m553734blw13cl454bh0000gn/T/DrJava-test-barretglass3007482003144796830/ABC2.java, line=1, col=28, msg=found raw type: java.util.ArrayList
[junit] missing type arguments for generic class java.util.ArrayList<E>)
[junit]
[junit] at edu.rice.cs.drjava.model.junit.JUnitErrorModelTest.testVerifyErrorHandledCorrectly_NOJOIN(JUnitErrorModelTest.java:271)
Removed the -xlint flag from compilation and now only this test is failing:
[junit] Testcase: testCompileFailsCorrectLineNumbers(edu.rice.cs.drjava.model.GlobalModelCompileErrorsTest): FAILED
[junit] location of first error should be between 20 and 29 inclusive (line 2), but was 32
[junit] junit.framework.AssertionFailedError: location of first error should be between 20 and 29 inclusive (line 2), but was 32
[junit] at edu.rice.cs.drjava.model.GlobalModelCompileErrorsTest.testCompileFailsCorrectLineNumbers(GlobalModelCompileErrorsTest.java:333)
All test cases now pass https://github.com/DrJavaAtRice/drjava/pull/25
Let's talk Wednesday and see if we can't merge into master this week. I want to resolve the ant run
issue Corky was having first.
Fixed the logic to pass the build directory to the library compiler.
Turns out you can’t just pass it the ‘-d’ command line arg, but instead need to set StandardLocation.CLASS_OUTPUT in the file manager for it to find the build dir. This seems to be working well now.
Background
"Prior to Java 6, DrJava was forced to treat Java compilers as completely separate libraries that DrJava dynamically discovered in the file system each time it was executed. It had to cope with the fact that there were several different versions of Java in use and several different compilers (with different APIs) for each version.
After Sun/Oracle became committed to supporting a solid comprehensive open source implementation of Java and access to the compiler was provided as part of the core Java libraries in Java 6, Sun/Oracle was forced to release the compiler (perhaps without some proprietary bits) to the open-source world. At this point, we could potentially change course, but the funding for the DrJava project (which started in 2000) ended before this juncture.
So we have limped along with the old framework. What I want to do now is only support the compiler in the library of the running JVM. How simple this approach is in principle in comparison to what DrJava has been doing in the past. Most of the existing infrastructure can be discarded if we can figure out how to cleanly cut it out. In some sense, the default compiler will become the only compiler but it will be accessed as part of the Java core libraries (namely in javax.tools), which in principle is much simpler. There is no searching and only one interface (as specified in Java documentation starting with Java 8). Programmatic access to the compiler was added to the Java libraries in Java 6, but we only need to support Java 8+, and each edition of Java typically adds more content (in backwards-compatible fashion) so do not need to worry about the differences between Java 6 and Java 8. We can Java 8 as the standard to which we will program and that content will be preserved in all future editions of Java (at least that has been the mantra of the Java platform).
I suggest that we initially add support for the library compiler in place of the existing default compiler embedded in drjava.jar (as tools.jar from a particular open-source distribution)." -- Corky
TODO: