diff --git a/.gitignore b/.gitignore
index 0dd9c852a..24425b5b2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,4 +14,7 @@ drjava/classes
drjava/drjava.jar
drjava/build.xml.*
drjava/coverage_report
-scratch
\ No newline at end of file
+scratch
+.idea/
+*.iml
+*.exec
\ No newline at end of file
diff --git a/drjava.jar b/drjava.jar
new file mode 100644
index 000000000..d78e4ee65
Binary files /dev/null and b/drjava.jar differ
diff --git a/drjava/.gitignore b/drjava/.gitignore
index 4c8e5864d..794f549de 100644
--- a/drjava/.gitignore
+++ b/drjava/.gitignore
@@ -1,3 +1,4 @@
drjava.jar
classes/
-
+arch/
+docs/
diff --git a/drjava/build.xml b/drjava/build.xml
index 8b1f25c78..8e72d38f9 100644
--- a/drjava/build.xml
+++ b/drjava/build.xml
@@ -1,4 +1,3 @@
-
-
+
-
+
+
+
+
-
-
-
-
+
+
+
+
+
@@ -184,10 +188,64 @@
******************* -->
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -200,9 +258,9 @@
-
-
@@ -346,7 +404,19 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -426,16 +496,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
-
+
@@ -455,7 +567,7 @@
-
+
@@ -464,6 +576,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -755,7 +905,7 @@
@@ -765,7 +915,6 @@
-
-
-
+
@@ -979,20 +1125,37 @@
-
-
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1010,30 +1173,27 @@
-
-
-
-
-
-
+
+
+
+
+
+
-
+
-
+
-
+
-
-
-
-
+
diff --git a/drjava/build_old.xml b/drjava/build_old.xml
new file mode 100644
index 000000000..37829a408
--- /dev/null
+++ b/drjava/build_old.xml
@@ -0,0 +1,1014 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/drjava/extlib/cldrdata.jar b/drjava/extlib/cldrdata.jar
new file mode 100644
index 000000000..e5191fab2
Binary files /dev/null and b/drjava/extlib/cldrdata.jar differ
diff --git a/drjava/extlib/dnsns.jar b/drjava/extlib/dnsns.jar
new file mode 100644
index 000000000..e9174da44
Binary files /dev/null and b/drjava/extlib/dnsns.jar differ
diff --git a/drjava/extlib/icedtea-sound.jar b/drjava/extlib/icedtea-sound.jar
new file mode 100644
index 000000000..97da2257b
Binary files /dev/null and b/drjava/extlib/icedtea-sound.jar differ
diff --git a/drjava/extlib/jaccess.jar b/drjava/extlib/jaccess.jar
new file mode 100644
index 000000000..846da5794
Binary files /dev/null and b/drjava/extlib/jaccess.jar differ
diff --git a/drjava/extlib/java-atk-wrapper.jar b/drjava/extlib/java-atk-wrapper.jar
new file mode 120000
index 000000000..d0b7bd0b2
--- /dev/null
+++ b/drjava/extlib/java-atk-wrapper.jar
@@ -0,0 +1 @@
+../../../../../../share/java/java-atk-wrapper.jar
\ No newline at end of file
diff --git a/drjava/extlib/libatk-wrapper.so b/drjava/extlib/libatk-wrapper.so
new file mode 120000
index 000000000..fed87c67c
--- /dev/null
+++ b/drjava/extlib/libatk-wrapper.so
@@ -0,0 +1 @@
+../../../../../x86_64-linux-gnu/jni/libatk-wrapper.so
\ No newline at end of file
diff --git a/drjava/extlib/localedata.jar b/drjava/extlib/localedata.jar
new file mode 100644
index 000000000..7fc65a096
Binary files /dev/null and b/drjava/extlib/localedata.jar differ
diff --git a/drjava/extlib/nashorn.jar b/drjava/extlib/nashorn.jar
new file mode 100644
index 000000000..71df18d9c
Binary files /dev/null and b/drjava/extlib/nashorn.jar differ
diff --git a/drjava/extlib/rt.jar b/drjava/extlib/rt.jar
new file mode 100644
index 000000000..186774f81
Binary files /dev/null and b/drjava/extlib/rt.jar differ
diff --git a/drjava/extlib/sunec.jar b/drjava/extlib/sunec.jar
new file mode 100644
index 000000000..90812e59c
Binary files /dev/null and b/drjava/extlib/sunec.jar differ
diff --git a/drjava/extlib/sunjce_provider.jar b/drjava/extlib/sunjce_provider.jar
new file mode 100644
index 000000000..a7b89cada
Binary files /dev/null and b/drjava/extlib/sunjce_provider.jar differ
diff --git a/drjava/extlib/sunpkcs11.jar b/drjava/extlib/sunpkcs11.jar
new file mode 100644
index 000000000..d0dc4d992
Binary files /dev/null and b/drjava/extlib/sunpkcs11.jar differ
diff --git a/drjava/lib/tools.jar b/drjava/extlib/tools.jar
similarity index 95%
rename from drjava/lib/tools.jar
rename to drjava/extlib/tools.jar
index f38baa1fb..f3a8ac5ff 100644
Binary files a/drjava/lib/tools.jar and b/drjava/extlib/tools.jar differ
diff --git a/drjava/extlib/zipfs.jar b/drjava/extlib/zipfs.jar
new file mode 100644
index 000000000..d0a9c5fca
Binary files /dev/null and b/drjava/extlib/zipfs.jar differ
diff --git a/drjava/lib/asm-6.0.jar b/drjava/lib/asm-6.0.jar
deleted file mode 100644
index cf2de272c..000000000
Binary files a/drjava/lib/asm-6.0.jar and /dev/null differ
diff --git a/drjava/lib/asm-9.6.jar b/drjava/lib/asm-9.6.jar
new file mode 100644
index 000000000..cc1c2cd8e
Binary files /dev/null and b/drjava/lib/asm-9.6.jar differ
diff --git a/drjava/lib/asm-commons-6.0.jar b/drjava/lib/asm-commons-6.0.jar
deleted file mode 100644
index 33ba0c463..000000000
Binary files a/drjava/lib/asm-commons-6.0.jar and /dev/null differ
diff --git a/drjava/lib/asm-commons-9.6.jar b/drjava/lib/asm-commons-9.6.jar
new file mode 100644
index 000000000..75f3bad86
Binary files /dev/null and b/drjava/lib/asm-commons-9.6.jar differ
diff --git a/drjava/lib/asm-tree-6.0.jar b/drjava/lib/asm-tree-6.0.jar
deleted file mode 100644
index 2aa9815c9..000000000
Binary files a/drjava/lib/asm-tree-6.0.jar and /dev/null differ
diff --git a/drjava/lib/asm-tree-9.6.jar b/drjava/lib/asm-tree-9.6.jar
new file mode 100644
index 000000000..9fe527587
Binary files /dev/null and b/drjava/lib/asm-tree-9.6.jar differ
diff --git a/drjava/lib/buildlib/asm-commons-9.6.jar b/drjava/lib/buildlib/asm-commons-9.6.jar
new file mode 100644
index 000000000..75f3bad86
Binary files /dev/null and b/drjava/lib/buildlib/asm-commons-9.6.jar differ
diff --git a/drjava/lib/buildlib/asm-debug-all-5.0.2.jar b/drjava/lib/buildlib/asm-debug-all-5.0.2.jar
new file mode 100644
index 000000000..834c9d09a
Binary files /dev/null and b/drjava/lib/buildlib/asm-debug-all-5.0.2.jar differ
diff --git a/drjava/lib/buildlib/bcel-6.0-SNAPSHOT.jar b/drjava/lib/buildlib/bcel-6.0-SNAPSHOT.jar
new file mode 100644
index 000000000..11a974b28
Binary files /dev/null and b/drjava/lib/buildlib/bcel-6.0-SNAPSHOT.jar differ
diff --git a/drjava/lib/buildlib/commons-lang-2.6.jar b/drjava/lib/buildlib/commons-lang-2.6.jar
new file mode 100644
index 000000000..98467d3a6
Binary files /dev/null and b/drjava/lib/buildlib/commons-lang-2.6.jar differ
diff --git a/drjava/lib/buildlib/dom4j-1.6.1.jar b/drjava/lib/buildlib/dom4j-1.6.1.jar
new file mode 100644
index 000000000..c8c4dbb92
Binary files /dev/null and b/drjava/lib/buildlib/dom4j-1.6.1.jar differ
diff --git a/drjava/lib/buildlib/findbugs-ant.jar b/drjava/lib/buildlib/findbugs-ant.jar
index 5e917ba50..c2ad778a6 100644
Binary files a/drjava/lib/buildlib/findbugs-ant.jar and b/drjava/lib/buildlib/findbugs-ant.jar differ
diff --git a/drjava/lib/buildlib/findbugs.jar b/drjava/lib/buildlib/findbugs.jar
new file mode 100644
index 000000000..b86140266
Binary files /dev/null and b/drjava/lib/buildlib/findbugs.jar differ
diff --git a/drjava/lib/buildlib/jFormatString.jar b/drjava/lib/buildlib/jFormatString.jar
new file mode 100644
index 000000000..bdcb8466b
Binary files /dev/null and b/drjava/lib/buildlib/jFormatString.jar differ
diff --git a/drjava/lib/buildlib/jacocoagent.jar b/drjava/lib/buildlib/jacocoagent.jar
new file mode 100644
index 000000000..9eedac24b
Binary files /dev/null and b/drjava/lib/buildlib/jacocoagent.jar differ
diff --git a/drjava/lib/buildlib/jacocoant.jar b/drjava/lib/buildlib/jacocoant.jar
index 09d4a4796..38c956372 100644
Binary files a/drjava/lib/buildlib/jacocoant.jar and b/drjava/lib/buildlib/jacocoant.jar differ
diff --git a/drjava/lib/buildlib/jaxen-1.1.6.jar b/drjava/lib/buildlib/jaxen-1.1.6.jar
new file mode 100644
index 000000000..52f47a4f4
Binary files /dev/null and b/drjava/lib/buildlib/jaxen-1.1.6.jar differ
diff --git a/drjava/lib/buildlib/jsr305.jar b/drjava/lib/buildlib/jsr305.jar
new file mode 100644
index 000000000..cc39b7383
Binary files /dev/null and b/drjava/lib/buildlib/jsr305.jar differ
diff --git a/drjava/lib/hamcrest-2.2.jar b/drjava/lib/hamcrest-2.2.jar
new file mode 100644
index 000000000..71065788d
Binary files /dev/null and b/drjava/lib/hamcrest-2.2.jar differ
diff --git a/drjava/lib/hamcrest-core-1.3.jar b/drjava/lib/hamcrest-core-1.3.jar
deleted file mode 100644
index 9d5fe16e3..000000000
Binary files a/drjava/lib/hamcrest-core-1.3.jar and /dev/null differ
diff --git a/drjava/lib/javalanglevels-base.jar b/drjava/lib/javalanglevels-base.jar
index 3c6925ebb..6b01892cc 100644
Binary files a/drjava/lib/javalanglevels-base.jar and b/drjava/lib/javalanglevels-base.jar differ
diff --git a/drjava/lib/junit.jar b/drjava/lib/junit.jar
index acc3c4320..6da55d8b8 100644
Binary files a/drjava/lib/junit.jar and b/drjava/lib/junit.jar differ
diff --git a/drjava/lib/org.jacoco.core-0.8.0.201801022044.jar b/drjava/lib/org.jacoco.core-0.8.0.201801022044.jar
deleted file mode 100644
index 55335c21d..000000000
Binary files a/drjava/lib/org.jacoco.core-0.8.0.201801022044.jar and /dev/null differ
diff --git a/drjava/lib/org.jacoco.core-0.8.11.202310140853.jar b/drjava/lib/org.jacoco.core-0.8.11.202310140853.jar
new file mode 100644
index 000000000..732e29681
Binary files /dev/null and b/drjava/lib/org.jacoco.core-0.8.11.202310140853.jar differ
diff --git a/drjava/lib/org.jacoco.report-0.8.0.201801022044.jar b/drjava/lib/org.jacoco.report-0.8.0.201801022044.jar
deleted file mode 100644
index f02e4a5e3..000000000
Binary files a/drjava/lib/org.jacoco.report-0.8.0.201801022044.jar and /dev/null differ
diff --git a/drjava/lib/org.jacoco.report-0.8.11.202310140853.jar b/drjava/lib/org.jacoco.report-0.8.11.202310140853.jar
new file mode 100644
index 000000000..e7a744062
Binary files /dev/null and b/drjava/lib/org.jacoco.report-0.8.11.202310140853.jar differ
diff --git a/drjava/lib/platform.jar b/drjava/lib/platform.jar
index f58174143..610ab4f40 100644
Binary files a/drjava/lib/platform.jar and b/drjava/lib/platform.jar differ
diff --git a/drjava/src/edu/rice/cs/drjava/DrJavaRoot.java b/drjava/src/edu/rice/cs/drjava/DrJavaRoot.java
index 90463cce4..16526258b 100644
--- a/drjava/src/edu/rice/cs/drjava/DrJavaRoot.java
+++ b/drjava/src/edu/rice/cs/drjava/DrJavaRoot.java
@@ -260,7 +260,7 @@ private static void _openCommandLineFiles(final MainFrame mf, String[] filesToOp
};
try {
if (isProjectFile) mf.openProject(command);
- else if (currFileName.endsWith(OptionConstants.EXTPROCESS_FILE_EXTENSION)) MainFrame.openExtProcessFile(file);
+// else if (currFileName.endsWith(OptionConstants.EXTPROCESS_FILE_EXTENSION)) MainFrame.openExtProcessFile(file);
else {
if (jump && (lineNo >= 0)) {
/* if a line number has been specified, open the file using MainFrame.open and jump to lineNo using
diff --git a/drjava/src/edu/rice/cs/drjava/config/DrJavaPropertySetupTest.java b/drjava/src/edu/rice/cs/drjava/config/DrJavaPropertySetupTest.java
index f962688db..1556b435b 100644
--- a/drjava/src/edu/rice/cs/drjava/config/DrJavaPropertySetupTest.java
+++ b/drjava/src/edu/rice/cs/drjava/config/DrJavaPropertySetupTest.java
@@ -949,8 +949,8 @@ public void testMisc() throws CloneNotSupportedException {
// process.separator
p = pm.getProperty("Config","process.separator");
- // enclosing.djapp.file
- p = pm.getProperty("Misc","enclosing.djapp.file");
+// // enclosing.djapp.file
+// p = pm.getProperty("Misc","enclosing.djapp.file");
// drjava.file
// during testing, this is the classes/base directory
diff --git a/drjava/src/edu/rice/cs/drjava/config/OptionConstants.java b/drjava/src/edu/rice/cs/drjava/config/OptionConstants.java
index 71abf2d28..2ba932770 100644
--- a/drjava/src/edu/rice/cs/drjava/config/OptionConstants.java
+++ b/drjava/src/edu/rice/cs/drjava/config/OptionConstants.java
@@ -79,8 +79,8 @@ public interface OptionConstants {
/** The alternative extension for a DrJava project file */
public static final String PROJECT_FILE_EXTENSION2 = ".xml";
- /** The extension for stand-alone DrJava external process file. */
- public static final String EXTPROCESS_FILE_EXTENSION = ".djapp";
+// /** The extension for stand-alone DrJava external process file. */
+// public static final String EXTPROCESS_FILE_EXTENSION = ".djapp";
/** The extension for a Java source file */
public static final String JAVA_FILE_EXTENSION = ".java";
@@ -112,8 +112,8 @@ public interface OptionConstants {
OLD_DJ2_FILE_EXTENSION, // = .dj2
DJ_FILE_EXTENSION }; // = .dj
- /** The configuration XML file that DrJava looks for inside a .djapp file */
- public static final String EXTPROCESS_FILE_NAME_INSIDE_JAR = "process" + EXTPROCESS_FILE_EXTENSION;
+// /** The configuration XML file that DrJava looks for inside a .djapp file */
+// public static final String EXTPROCESS_FILE_NAME_INSIDE_JAR = "process" + EXTPROCESS_FILE_EXTENSION;
/** The extension for a text file */
public static final String TEXT_FILE_EXTENSION = ".txt";
@@ -303,7 +303,9 @@ static class LookAndFeels {
/** @return the look-and-feel class name to use by default */
public static String getDefaultLookAndFeel() {
if (PlatformFactory.ONLY.isMacPlatform())
- return UIManager.getSystemLookAndFeelClassName(); // Mac: Let the system decide.
+ return "javax.swing.plaf.nimbus.NimbusLookAndFeel";
+ // TODO: fix this up to work with the proper look and feel -> Mac was causing problems
+// return UIManager.getSystemLookAndFeelClassName(); // Mac: Let the system decide.
else // Set CrossPlatform "Nimbus" LookAndFeel
try {
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels())
@@ -1797,11 +1799,11 @@ public static ArrayList evaluate() {
new StringOption("",""),
new Vector());
- /** The script file (or "" if none) of saved external processes. */
- public static final VectorOption EXTERNAL_SAVED_ENCLOSING_DJAPP_FILES =
- new VectorOption(EXTERNAL_SAVED_PREFIX + "enclosingdjappfiles",
- new StringOption("",""),
- new Vector());
+// /** The script file (or "" if none) of saved external processes. */
+// public static final VectorOption EXTERNAL_SAVED_ENCLOSING_DJAPP_FILES =
+// new VectorOption(EXTERNAL_SAVED_PREFIX + "enclosingdjappfiles",
+// new StringOption("",""),
+// new Vector());
/** Notification of new versions. */
public static final ArrayList NEW_VERSION_NOTIFICATION_CHOICES =
diff --git a/drjava/src/edu/rice/cs/drjava/model/AbstractGlobalModel.java b/drjava/src/edu/rice/cs/drjava/model/AbstractGlobalModel.java
index 67df370c6..6f9ffdb70 100644
--- a/drjava/src/edu/rice/cs/drjava/model/AbstractGlobalModel.java
+++ b/drjava/src/edu/rice/cs/drjava/model/AbstractGlobalModel.java
@@ -364,7 +364,8 @@ public void optionChanged(OptionEvent oce) {
// ----- STATE -----
- /** Specifies the state of the navigator pane. The global model delegates the compileAll command to the _state.
+ /** Specifies the state of the navigator pane.
+ * The global model delegates the compileAll command to the _state.
* FileGroupingState synchronization is handled by the compilerModel (??).
*/
protected volatile FileGroupingState _state;
@@ -3474,40 +3475,44 @@ private File _locateClassFile() {
_log.log("_locateClassFile() failed for " + this + " because getQualifedClassName returned ClassNotFound");
return FileOps.NULL_FILE; /* No source class name */
}
-// _log.log("In _locateClassFile, className = " + className);
+ _log.log("In _locateClassFile, className = " + className);
String ps = System.getProperty("file.separator");
// replace periods with the System's file separator
className = StringOps.replace(className, ".", ps);
String fileName = className + ".class";
-// _log.log("In _locateClassFile, classfileName = " + fileName);
+ _log.log("In _locateClassFile, classfileName = " + fileName);
// Check source root set (open files)
ArrayList roots = new ArrayList();
-// _log.log("build directory = " + getBuildDirectory());
+ File bd = getBuildDirectory();
- if (getBuildDirectory() != FileOps.NULL_FILE) roots.add(getBuildDirectory());
+ _log.log("build directory = " + bd);
- // Add the current document to the beginning of the roots list
+ // Place the build directory at the front of the roots list
+ if (bd != FileOps.NULL_FILE) roots.add(getBuildDirectory());
+
+ // Add the current document to the end (formerly beginning) of the roots list; in the command line class file
+ // layout, class files reside in same directory as corresponding source files.
try {
File root = getSourceRoot();
-// _log.log("Directory " + root + " added to list of source roots");
- roots.add(root);
+ _log.log("Directory " + root + " added to list of class file roots");
+ if (! roots.contains(root)) roots.add(root);
}
catch (InvalidPackageException ipe) {
try {
-// _log.log(this + " has no source root, using parent directory instead");
+ _log.log(this + " has no source root, using parent directory of this source document instead");
File root = getFile().getParentFile();
if (root != FileOps.NULL_FILE) {
roots.add(root);
-// _log.log("Added parent directory " + root + " to list of source roots");
+ _log.log("Added parent directory " + root + " to list of class file roots");
}
}
catch(NullPointerException e) { throw new UnexpectedException(e); }
catch(FileMovedException fme) {
// Moved, but we'll add the old file to the set anyway
- _log.log("File for " + this + "has moved; adding parent directory to list of roots");
+ _log.log("File for " + this + "has moved; adding parent directory of this source document instead");
File root = fme.getFile().getParentFile();
if (root != FileOps.NULL_FILE) roots.add(root);
}
@@ -3515,11 +3520,11 @@ private File _locateClassFile() {
File classFile = findFileInPaths(fileName, roots);
if (classFile != FileOps.NULL_FILE) {
-// _log.log("Found source file " + classFile + " for " + this);
+ _log.log("Found class file " + classFile + " for " + this);
return classFile;
}
-// _log.log(this + " not found on path of source roots");
+ _log.log(fileName + " not found on list of class file roots");
// Class not on source root set, check system classpath
classFile = findFileInPaths(fileName, ReflectUtil.SYSTEM_CLASS_PATH);
diff --git a/drjava/src/edu/rice/cs/drjava/model/BrowserHistoryManager.java b/drjava/src/edu/rice/cs/drjava/model/BrowserHistoryManager.java
index 4656a0ceb..5a224f672 100644
--- a/drjava/src/edu/rice/cs/drjava/model/BrowserHistoryManager.java
+++ b/drjava/src/edu/rice/cs/drjava/model/BrowserHistoryManager.java
@@ -140,7 +140,7 @@ private void shrinkManager() {
}
/** Remove the last region from the given stack and clean up.
- * @param stack the non-empty ArrayDeque() to be shrunk.
+ * @param stack the non-empty ArrayDeque to be shrunk.
*/
public void removeLast(final ArrayDeque stack) {
assert ! stack.isEmpty();
diff --git a/drjava/src/edu/rice/cs/drjava/model/DefaultGlobalModel.java b/drjava/src/edu/rice/cs/drjava/model/DefaultGlobalModel.java
index da9f2a3c7..1c7aaca29 100644
--- a/drjava/src/edu/rice/cs/drjava/model/DefaultGlobalModel.java
+++ b/drjava/src/edu/rice/cs/drjava/model/DefaultGlobalModel.java
@@ -44,9 +44,7 @@
import edu.rice.cs.drjava.config.BooleanOption;
import edu.rice.cs.drjava.model.FileSaveSelector;
import edu.rice.cs.drjava.model.JDKDescriptor;
-import edu.rice.cs.drjava.model.compiler.DummyCompilerListener;
-//import edu.rice.cs.drjava.model.compiler.EclipseCompiler;
-//import edu.rice.cs.drjava.model.compiler.descriptors.EclipseDescriptor;
+import edu.rice.cs.drjava.model.compiler.*;
import edu.rice.cs.drjava.model.definitions.ClassNameNotFoundException;
import edu.rice.cs.drjava.model.definitions.InvalidPackageException;
import edu.rice.cs.drjava.model.debug.Breakpoint;
@@ -65,10 +63,6 @@
import edu.rice.cs.drjava.model.repl.InteractionsListener;
import edu.rice.cs.drjava.model.repl.InteractionsScriptModel;
import edu.rice.cs.drjava.model.repl.newjvm.MainJVM;
-import edu.rice.cs.drjava.model.compiler.CompilerListener;
-import edu.rice.cs.drjava.model.compiler.CompilerModel;
-import edu.rice.cs.drjava.model.compiler.DefaultCompilerModel;
-import edu.rice.cs.drjava.model.compiler.CompilerInterface;
import edu.rice.cs.drjava.model.junit.DefaultJUnitModel;
import edu.rice.cs.drjava.model.junit.JUnitModel;
@@ -79,10 +73,10 @@
import edu.rice.cs.plt.reflect.ReflectUtil;
import edu.rice.cs.plt.tuple.Pair;
+import edu.rice.cs.util.AbsRelFile;
import edu.rice.cs.util.FileOpenSelector;
import edu.rice.cs.util.FileOps;
import edu.rice.cs.util.NullFile;
-import edu.rice.cs.util.AbsRelFile;
import edu.rice.cs.util.OperationCanceledException;
import edu.rice.cs.util.UnexpectedException;
import edu.rice.cs.util.swing.Utilities;
@@ -185,18 +179,23 @@ public void activeCompilerChanged() {
/* CONSTRUCTORS */
/** Constructs a new GlobalModel. Creates a new MainJVM and starts its Interpreter JVM. */
public DefaultGlobalModel() {
- Iterable extends JDKToolsLibrary> tools = findLibraries();
+ Iterable extends JDKToolsLibrary> tools = findLibraries(); // findLibraries should be called findTools
List compilers = new LinkedList();
-
+
+ // TODO: should this be done a different way?
+ JavaxToolsCompiler javaxCompiler = new JavaxToolsCompiler();
+ compilers.add(javaxCompiler);
+
/* Note: the only debugger used in DrJava is JPDADebugger in the DrJava code base which relies
* on machinery provided by the tools.jar library included in every Java JDK (up through JDK 8). A copy of the
* tools.jar library from Java 8 Open JDK is included in the drjava.jar file.
*/
_debugger = null;
_javadocModel = null;
+ /* Gather tools: a list compilers, a debugger, and a javadoc tool. */
for (JDKToolsLibrary t : tools) {
// Utilities.show("Found tools.jar library: " + t);
- if (t.compiler().isAvailable() && t.version().supports(JavaVersion.JAVA_7)) compilers.add(t.compiler());
+ if (t.compiler().isAvailable() && t.version().supports(JavaVersion.JAVA_8)) compilers.add(t.compiler());
if (_debugger == null && t.debugger().isAvailable()) { _debugger = t.debugger(); }
if (_javadocModel == null && t.javadoc().isAvailable()) { _javadocModel = t.javadoc(); }
}
@@ -205,7 +204,7 @@ public DefaultGlobalModel() {
File workDir = Utilities.TEST_MODE ? new File(System.getProperty("user.home")) : getWorkingDirectory();
_jvm = new MainJVM(workDir);
-// AbstractMasterJVM._log.log(this + " has created a new MainJVM");
+ _log.log(this + " has created a new MainJVM");
_compilerModel = new DefaultCompilerModel(this, compilers);
_junitModel = new DefaultJUnitModel(_jvm, _compilerModel, this);
_interactionsDocument = new InteractionsDJDocument(_notifier);
diff --git a/drjava/src/edu/rice/cs/drjava/model/GlobalModelCompileErrorsTest.java b/drjava/src/edu/rice/cs/drjava/model/GlobalModelCompileErrorsTest.java
index a13c408e3..6cf222f49 100644
--- a/drjava/src/edu/rice/cs/drjava/model/GlobalModelCompileErrorsTest.java
+++ b/drjava/src/edu/rice/cs/drjava/model/GlobalModelCompileErrorsTest.java
@@ -331,7 +331,7 @@ public void testCompileFailsCorrectLineNumbers() throws BadLocationException, IO
Position p1 = cme.getPosition(ce1);
Position p2 = cme.getPosition(ce2);
assertTrue("location of first error should be between 20 and 29 inclusive (line 2), but was " + p1.getOffset(),
- p1.getOffset() <= 20 && p1.getOffset() <= 29);
+ p1.getOffset() >= 20 && p1.getOffset() <= 29);
assertTrue("location of error should be after 34 (line 3 or 4)", p2.getOffset() >= 34);
debug.logEnd();
diff --git a/drjava/src/edu/rice/cs/drjava/model/JDKDescriptor.java b/drjava/src/edu/rice/cs/drjava/model/JDKDescriptor.java
index 25020324c..b45915f03 100644
--- a/drjava/src/edu/rice/cs/drjava/model/JDKDescriptor.java
+++ b/drjava/src/edu/rice/cs/drjava/model/JDKDescriptor.java
@@ -40,8 +40,7 @@
import edu.rice.cs.plt.iter.IterUtil;
/** A description of a JDK.
- * Put subclasses of JDKDescriptor in the edu.rice.cs.drjava.model.compiler.descriptors package for DrJava
- * to find. */
+ * Put subclasses of JDKDescriptor in the edu.rice.cs.drjava.model.compiler.descriptors package for DrJava to find. */
public abstract class JDKDescriptor {
/** Return the name of this JDK.
* @return name */
@@ -181,7 +180,7 @@ public String getAdapterForDebugger(JavaVersion.FullVersion guessedVersion) {
return JDKToolsLibrary.adapterForDebugger(guessedVersion);
}
public boolean containsCompiler(File f) { return true; }
- public JavaVersion getMinimumMajorVersion() { return JavaVersion.JAVA_7; }
+ public JavaVersion getMinimumMajorVersion() { return JavaVersion.JAVA_8; }
public Iterable getAdditionalCompilerFiles(File compiler) throws FileNotFoundException {
return IterUtil.empty();
}
diff --git a/drjava/src/edu/rice/cs/drjava/model/JDKToolsLibrary.java b/drjava/src/edu/rice/cs/drjava/model/JDKToolsLibrary.java
index 2dc01eeb2..be2b40067 100644
--- a/drjava/src/edu/rice/cs/drjava/model/JDKToolsLibrary.java
+++ b/drjava/src/edu/rice/cs/drjava/model/JDKToolsLibrary.java
@@ -94,32 +94,36 @@ public boolean isValid() {
public String toString() { return _jdkDescriptor.getDescription(_version); }
- public static String adapterForCompiler(JavaVersion.FullVersion version) {
- switch (version.majorVersion()) {
- case FUTURE: return "edu.rice.cs.drjava.model.compiler.Javac170Compiler";
- case JAVA_8: return "edu.rice.cs.drjava.model.compiler.Javac170Compiler";
- case JAVA_7: return "edu.rice.cs.drjava.model.compiler.Javac170Compiler";
- case JAVA_6: {
- switch (version.vendor()) {
- case OPENJDK: return "edu.rice.cs.drjava.model.compiler.Javac160OpenJDKCompiler";
- case UNKNOWN: return null;
- default: return "edu.rice.cs.drjava.model.compiler.Javac160Compiler";
- }
- }
- case JAVA_5: return "edu.rice.cs.drjava.model.compiler.Javac150Compiler";
- default: return null;
- }
+ public static String adapterForCompiler(JavaVersion.FullVersion version) {
+ return "edu.rice.cs.drjava.model.compiler.Javac170Compiler";
+ /* formerly the following */
+// switch (version.majorVersion()) {
+// case FUTURE: return "edu.rice.cs.drjava.model.compiler.Javac170Compiler";
+// case JAVA_8: return "edu.rice.cs.drjava.model.compiler.Javac170Compiler";
+// case JAVA_7: return "edu.rice.cs.drjava.model.compiler.Javac170Compiler";
+// case JAVA_6: {
+// switch (version.vendor()) {
+// case OPENJDK: return "edu.rice.cs.drjava.model.compiler.Javac160OpenJDKCompiler";
+// case UNKNOWN: return null;
+// default: return "edu.rice.cs.drjava.model.compiler.Javac160Compiler";
+// }
+// }
+// case JAVA_5: return "edu.rice.cs.drjava.model.compiler.Javac150Compiler";
+// default: return null;
+// }
}
- public static String adapterForDebugger(JavaVersion.FullVersion version) {
- switch (version.majorVersion()) {
- case FUTURE:
- case JAVA_8:
- case JAVA_7:
- case JAVA_6:
- case JAVA_5: return "edu.rice.cs.drjava.model.debug.jpda.JPDADebugger";
- default: return null;
- }
+ public static String adapterForDebugger(JavaVersion.FullVersion version) {
+ return "edu.rice.cs.drjava.model.debug.jpda.JPDADebugger";
+ /* formerly */
+// switch (version.majorVersion()) {
+// case FUTURE:
+// case JAVA_8:
+// case JAVA_7:
+// case JAVA_6:
+// case JAVA_5: return "edu.rice.cs.drjava.model.debug.jpda.JPDADebugger";
+// default: return null;
+// }
}
protected static CompilerInterface getCompilerInterface(String className, FullVersion version) {
diff --git a/drjava/src/edu/rice/cs/drjava/model/JarJDKToolsLibrary.java b/drjava/src/edu/rice/cs/drjava/model/JarJDKToolsLibrary.java
index f11e6866f..e0f073ba0 100644
--- a/drjava/src/edu/rice/cs/drjava/model/JarJDKToolsLibrary.java
+++ b/drjava/src/edu/rice/cs/drjava/model/JarJDKToolsLibrary.java
@@ -416,7 +416,7 @@ protected static LinkedHashMap> getDefaultSearchRoots()
String envJavaHome = null;
String programFiles = null;
String systemDrive = null;
- if (JavaVersion.CURRENT.supports(JavaVersion.JAVA_7)) { /* formerly JavaVersion.JAVA_5 */
+ if (JavaVersion.CURRENT.supports(JavaVersion.JAVA_8)) { /* formerly JavaVersion.JAVA_5 and later JavaVersion.JAVA_7 */
// System.getenv is deprecated under 1.3 and 1.4, and may throw a java.lang.Error (!),
// which we'd rather not have to catch
envJavaHome = System.getenv("JAVA_HOME");
@@ -446,44 +446,47 @@ protected static LinkedHashMap> getDefaultSearchRoots()
addIfDir(new File(programFiles), roots);
}
- /* The following two lines were added to support OpenJDK8 on Windows 10. */
+ /* The following three lines were added to support OpenJDK8 on Windows 10/11. */
addIfDir(new File("/C:/Program Files/Zulu/zulu-8"), roots);
addIfDir(new File("/C:/Program Files (x86)/Zulu/zulu-8"), roots);
+ addIfDir(new File("/C:/Program Files/Amazon Corretto"), roots);
addIfDir(new File("/C:/Program Files/Java"), roots);
addIfDir(new File("/C:/Program Files (x86)/Java"), roots);
- addIfDir(new File("/C:/Program Files"), roots);
- addIfDir(new File("/C:/Program Files (x86)"), roots);
+// addIfDir(new File("/C:/Program Files"), roots);
+// addIfDir(new File("/C:/Program Files (x86)"), roots);
if (systemDrive != null) {
addIfDir(new File(systemDrive, "Java"), roots);
addIfDir(new File(systemDrive), roots);
}
- addIfDir(new File("/C:/Java"), roots);
- addIfDir(new File("/C:"), roots);
+// addIfDir(new File("/C:/Java"), roots);
+// addIfDir(new File("/C:"), roots);
/* Entries for Mac OS X */
addIfDir(new File("/System/Library/Java/JavaVirtualMachines"), roots);
addIfDir(new File("/Library/Java/JavaVirtualMachines"), roots);
// addIfDir(new File("/System/Library/Java/JavaVirtualMachines"), roots);
- /* Entries for Linux */
- addIfDir(new File("/usr/java"), roots);
- addIfDir(new File("/usr/j2se"), roots);
- addIfDir(new File("/usr"), roots);
- addIfDir(new File("/usr/local/java"), roots);
- addIfDir(new File("/usr/local/j2se"), roots);
- addIfDir(new File("/usr/local"), roots);
+// /* Entries for Linux */
+// addIfDir(new File("/usr/java"), roots);
+// addIfDir(new File("/usr/j2se"), roots);
+// addIfDir(new File("/usr"), roots);
+// addIfDir(new File("/usr/local/java"), roots);
+// addIfDir(new File("/usr/local/j2se"), roots);
+// addIfDir(new File("/usr/local"), roots);
/* Entries for Linux java packages */
addIfDir(new File("/usr/lib/jvm"), roots);
addIfDir(new File("/usr/lib/jvm/java-8-oracle"), roots);
addIfDir(new File("/usr/lib/jvm/java-8-openjdk"), roots);
- addIfDir(new File("/usr/lib/jvm/java-7-oracle"), roots);
- addIfDir(new File("/usr/lib/jvm/java-7-openjdk"), roots);
- addIfDir(new File("/usr/lib/jvm/java-6-sun"), roots);
- addIfDir(new File("/usr/lib/jvm/java-6-openjdk"), roots);
- addIfDir(new File("/usr/lib/jvm/java-1.5.0-sun"), roots);
+
+ /* Legacy versions of Java -- no longer supported */
+// addIfDir(new File("/usr/lib/jvm/java-7-oracle"), roots);
+// addIfDir(new File("/usr/lib/jvm/java-7-openjdk"), roots);
+// addIfDir(new File("/usr/lib/jvm/java-6-sun"), roots);
+// addIfDir(new File("/usr/lib/jvm/java-6-openjdk"), roots);
+// addIfDir(new File("/usr/lib/jvm/java-1.5.0-sun"), roots);
// addIfDir(new File("/home/javaplt/java/Linux-i686"), roots);
diff --git a/drjava/src/edu/rice/cs/drjava/model/compiler/CompilerInterface.java b/drjava/src/edu/rice/cs/drjava/model/compiler/CompilerInterface.java
index 763b87377..40c850d19 100644
--- a/drjava/src/edu/rice/cs/drjava/model/compiler/CompilerInterface.java
+++ b/drjava/src/edu/rice/cs/drjava/model/compiler/CompilerInterface.java
@@ -81,8 +81,7 @@ List extends DJError> compile(List extends File> files, List extends File>
/** @return string to display in a combo box (generally {@code getName()}) */
String toString();
- /** A compiler can instruct DrJava to include additional elements for the boot
- * class path of the Interactions JVM.
+ /** A compiler can instruct DrJava to include additional elements for the boot class path of the Interactions JVM.
* @return list of files on the class path
*/
List additionalBootClassPathForInteractions();
diff --git a/drjava/src/edu/rice/cs/drjava/model/compiler/JavacCompiler.java b/drjava/src/edu/rice/cs/drjava/model/compiler/JavacCompiler.java
index 3b8a73496..9b6ad5740 100644
--- a/drjava/src/edu/rice/cs/drjava/model/compiler/JavacCompiler.java
+++ b/drjava/src/edu/rice/cs/drjava/model/compiler/JavacCompiler.java
@@ -59,12 +59,10 @@ public abstract class JavacCompiler implements CompilerInterface {
/** The set of class names that are run as ACM Java Task Force library programs. */
protected static final Set ACM_PROGRAM_CLASSES = new HashSet();
static {
- Collections.addAll(ACM_PROGRAM_CLASSES, new String[] {
- "acm.program.Program",
- "acm.graphics.GTurtle"
- });
+ Collections.addAll(ACM_PROGRAM_CLASSES, new String[] {"acm.program.Program", "acm.graphics.GTurtle"});
}
+ /** Standard Constructor */
protected JavacCompiler(JavaVersion.FullVersion version, String location, List extends File> defaultBootClassPath) {
_version = version;
_location = location;
diff --git a/drjava/src/edu/rice/cs/drjava/model/compiler/JavaxToolsCompiler.java b/drjava/src/edu/rice/cs/drjava/model/compiler/JavaxToolsCompiler.java
new file mode 100644
index 000000000..963910832
--- /dev/null
+++ b/drjava/src/edu/rice/cs/drjava/model/compiler/JavaxToolsCompiler.java
@@ -0,0 +1,435 @@
+package edu.rice.cs.drjava.model.compiler;
+
+import edu.rice.cs.drjava.DrJava;
+import edu.rice.cs.drjava.config.OptionConstants;
+import edu.rice.cs.drjava.model.DJError;
+import edu.rice.cs.drjava.model.DrJavaFileUtils;
+import edu.rice.cs.drjava.ui.SmartSourceFilter;
+import edu.rice.cs.plt.reflect.JavaVersion;
+import edu.rice.cs.util.ArgumentTokenizer;
+
+import javax.swing.filechooser.FileFilter;
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.util.*;
+import javax.tools.*; /* including ToolProvider, StandardLocation, DiagnosticCollector */
+
+/** The CompilerInterface for the javax.tools compiler embedded in the executing JVM.
+ * Manages the auxiliary naming methods.(?)
+ */
+
+public class JavaxToolsCompiler implements CompilerInterface {
+ /** The set of class names that are run as ACM Java Task Force library programs. */
+ protected static final Set ACM_PROGRAM_CLASSES = new HashSet();
+ static {
+ Collections.addAll(ACM_PROGRAM_CLASSES, new String[] {"acm.program.Program", "acm.graphics.GTurtle"});
+ }
+ private final JavaCompiler compiler;
+
+ /** Standard Constructor */
+ public JavaxToolsCompiler() { this.compiler = ToolProvider.getSystemJavaCompiler(); }
+
+ public boolean isAvailable() { return this.compiler != null; }
+
+ public List extends DJError> compile(List extends File> files, List extends File> classPath,
+ List extends File> sourcePath, File destination,
+ List extends File> bootClassPath, String sourceVersion, boolean showWarnings) {
+ // Check if compiler is available
+ if (compiler == null) {
+ List errors = new ArrayList<>();
+ errors.add(new DJError("The SystemJavaCompiler is not available", false));
+ return errors;
+ }
+
+ // Set up the file manager
+ StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
+
+ // Set the classpath, source path, and bootclasspath
+ try {
+ if (classPath != null) {
+ fileManager.setLocation(StandardLocation.CLASS_PATH, classPath);
+ }
+ if (sourcePath != null) {
+ fileManager.setLocation(StandardLocation.SOURCE_PATH, sourcePath);
+ }
+ if (bootClassPath != null) {
+ fileManager.setLocation(StandardLocation.PLATFORM_CLASS_PATH, bootClassPath);
+ }
+ } catch (IOException e) {
+ List errors = new ArrayList<>();
+ errors.add(new DJError("Error setting paths: " + e.getMessage(), false));
+ return errors;
+ }
+
+ // Convert files to a format the compiler understands
+ Iterable extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(files);
+
+ // Prepare the compilation options
+ /* Question (by Corky): is the "-source" option necessary? The JavaxTools compiler is part of the executing JVM. */
+ List optionList = new ArrayList<>();
+ if (sourceVersion != null) {
+ optionList.add("-source");
+ optionList.add(sourceVersion);
+ }
+ if (destination != null) {
+ try {
+ fileManager.setLocation(StandardLocation.CLASS_OUTPUT, Collections.singletonList(destination));
+ } catch (IOException e) {
+ List errors = new ArrayList<>();
+ errors.add(new DJError("Error setting build directory: " + e.getMessage(), false));
+ return errors;
+ }
+ // This doesn't work for javax.tools compiler
+ // optionList.add("-d");
+ // optionList.add(destination.getAbsolutePath());
+ }
+
+ // Prepare a diagnostic collector to collect compile errors
+ DiagnosticCollector diagnostics = new DiagnosticCollector<>();
+
+ // Create a compilation task
+ JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnostics, optionList, null, compilationUnits);
+
+ // Perform the compile task
+ boolean success = task.call();
+
+ // Process diagnostics to create DJError list
+ List errors = new ArrayList<>();
+ for (Diagnostic extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) {
+ DJError error = new DJError(new File(diagnostic.getSource().toUri()),
+ (int) diagnostic.getLineNumber() - 1, // DJError adds 1 to this number.
+ (int) diagnostic.getColumnNumber() - 1, // Fixes the cursor position offset.
+ diagnostic.getMessage(null),
+ diagnostic.getKind() == Diagnostic.Kind.ERROR);
+ errors.add(error);
+ }
+
+ // If compilation failed and no errors were reported, add a generic error message
+ if (!success && errors.isEmpty()) {
+ errors.add(new DJError("Compilation failed with unknown error", true));
+ }
+
+ return errors;
+ }
+ /* Question (Corky): Shouldn't we retreive the version of this System (JVM). */
+ public JavaVersion version() { return JavaVersion.JAVA_8; }
+
+ public String getName() { return "javax.tools"; }
+
+ public String getDescription() { return "Standard compiler in javax.tools"; }
+
+ public String toString() { return getName(); }
+
+ public List additionalBootClassPathForInteractions() { return Collections.emptyList(); }
+
+ /** Transform the command line to be interpreted into something the Interactions JVM can use.
+ * This replaces "java MyClass a b c" with Java code to call MyClass.main(new String[]{"a","b","c"}).
+ * "import MyClass" is not handled here.
+ * transformCommands should support at least "run", "java" and "applet".
+ * @param interactionsString unprocessed command line
+ * @return command line with commands transformed */
+ public String transformCommands(String interactionsString) {
+ if (interactionsString.startsWith("java ")) {
+ interactionsString = transformJavaCommand(interactionsString);
+ }
+ else if (interactionsString.startsWith("applet ")) {
+ interactionsString = transformAppletCommand(interactionsString);
+ }
+ else if (interactionsString.startsWith("run ")) {
+ interactionsString = transformRunCommand(interactionsString);
+ }
+ return interactionsString;
+ }
+
+ public static String transformJavaCommand(String s) {
+ // check the return type and public access before executing, per bug #1585210
+ String command =
+ "try '{'\n" +
+ " java.lang.reflect.Method m = {0}.class.getMethod(\"main\", java.lang.String[].class);\n" +
+ " if (!m.getReturnType().equals(void.class)) throw new java.lang.NoSuchMethodException();\n" +
+ "'}'\n" +
+ "catch (java.lang.NoSuchMethodException e) '{'\n" +
+ " throw new java.lang.NoSuchMethodError(\"main\");\n" +
+ "'}'\n" +
+ "{0}.main(new String[]'{'{1}'}');";
+ return _transformCommand(s, command);
+ }
+
+ public static String transformAppletCommand(String s) {
+ return _transformCommand(s,"edu.rice.cs.plt.swing.SwingUtil.showApplet(new {0}({1}), 400, 300);");
+ }
+
+ /** This method performs the "smart run". Unfortunately, we don't get the right static error messages.
+ * @param s full command line, i.e. "run MyClass 1 2 3"
+ * @param c class to be run, i.e. MyClass.class
+ * @throws Throwable if something goes wrong
+ */
+ public static void runCommand(String s, Class> c) throws Throwable {
+ if (s.endsWith(";")) s = _deleteSemiColon(s);
+ List tokens = ArgumentTokenizer.tokenize(s, true);
+ String[] args = new String[tokens.size() - 2];
+ for (int i = 2; i < tokens.size(); i++) {
+ String t = tokens.get(i);
+ args[i - 2] = t.substring(1, t.length() - 1);
+ }
+
+ boolean isProgram = false;
+ boolean isApplet = false;
+ Class> oldC = c;
+ while(c != null) {
+ if (ACM_PROGRAM_CLASSES.contains(c.getName())) { isProgram = true; break; }
+ c = c.getSuperclass();
+ }
+ c = oldC;
+ if (!isProgram) {
+ try {
+ // if this doesn't throw, c is a subclass of Applet
+ c.asSubclass(java.applet.Applet.class);
+ isApplet = true;
+ } catch(ClassCastException cce) { }
+ }
+
+ java.lang.reflect.Method m = null;
+ if (isApplet) {
+ try {
+ m = c.getMethod("main", java.lang.String[].class);
+ if (!m.getReturnType().equals(void.class)) { m = null; }
+ }
+ catch (java.lang.NoSuchMethodException e) { m = null; }
+ if (m == null) {
+ java.applet.Applet instance = null;
+ if (args.length == 0) {
+ try {
+ // try default (nullary) constructor first
+ Constructor> ctor = c.getConstructor();
+ instance = java.applet.Applet.class.cast(ctor.newInstance());
+ }
+ catch(NoSuchMethodException | InstantiationException | IllegalAccessException nsme) {
+ instance = null;
+ }
+ catch(java.lang.reflect.InvocationTargetException ite) {
+ if (ite.getCause()!=null) {
+ throw ite.getCause();
+ }
+ else {
+ System.err.println("Error: Please turn off 'Smart Run' or use 'java' command instead of 'run'.");
+ }
+ }
+ if (instance == null) {
+ try {
+ // try String[] constructor next
+ Constructor> ctor = c.getConstructor(String[].class);
+ instance = java.applet.Applet.class.cast(ctor.newInstance(new Object[] { new String[0] }));
+ }
+ catch(NoSuchMethodException | InstantiationException | IllegalAccessException nsme) {
+ instance = null;
+ }
+ catch(java.lang.reflect.InvocationTargetException ite) {
+ if (ite.getCause()!=null) {
+ throw ite.getCause();
+ }
+ else {
+ System.err.println("Error: Please turn off 'Smart Run' or use 'java' command instead of 'run'.");
+ return;
+ }
+ }
+ }
+ if (instance == null) {
+ System.err.println("Static Error: This applet does not have a default constructor or a constructor "+
+ "accepting String[].");
+ return;
+ }
+ }
+ else {
+ try {
+ // try String[] constructor
+ Constructor> ctor = c.getConstructor(String[].class);
+ instance = java.applet.Applet.class.cast(ctor.newInstance(new Object[] { args }));
+ }
+ catch(NoSuchMethodException | InstantiationException | IllegalAccessException nsme) {
+ instance = null;
+ }
+ catch(java.lang.reflect.InvocationTargetException ite) {
+ if (ite.getCause()!=null) {
+ throw ite.getCause();
+ }
+ else {
+ System.err.println("Error: Please turn off 'Smart Run' or use 'java' command instead of 'run'.");
+ return;
+ }
+ }
+ if (instance == null) {
+ System.err.println("Static Error: This applet does not have a constructor accepting String[].");
+ return;
+ }
+ }
+ edu.rice.cs.plt.swing.SwingUtil.showApplet(instance, 400, 300);
+ }
+ }
+ else {
+ try {
+ m = c.getMethod("main", java.lang.String[].class);
+ if (!m.getReturnType().equals(void.class)) {
+ System.err.println("Static Error: This class does not have a static void main method accepting String[].");
+ m = null;
+ }
+ }
+ catch (java.lang.NoSuchMethodException e) {
+ System.err.println("Static Error: This class does not have a static void main method accepting String[].");
+ m = null;
+ }
+ }
+ if (m != null) {
+ if (isProgram) {
+ String[] newArgs = new String[args.length+1];
+ newArgs[0] = "code="+c.getName();
+ System.arraycopy(args, 0, newArgs, 1, args.length);
+ args = newArgs;
+ }
+ try {
+ m.setAccessible(true);
+ m.invoke(null, new Object[] { args });
+ }
+ catch(SecurityException | IllegalAccessException se) {
+ System.err.println("Error: Please turn off 'Smart Run' or use 'java' command instead of 'run'.");
+ }
+ catch(java.lang.reflect.InvocationTargetException ite) {
+ if (ite.getCause()!=null) {
+ throw ite.getCause();
+ }
+ else {
+ System.err.println("Error: Please turn off 'Smart Run' or use 'java' command instead of 'run'.");
+ }
+ }
+ }
+ }
+
+ /** This is a method that automatically detects if
+ * a) the class is an ACM Java Task Force program (subclass of acm.program.Program)
+ * b) an applet
+ * c) a class with a static main method
+ *
+ * If a), then DrJava inserts "code=MyClass" as argument 0.
+ * If b), then DrJava performs the same as "applet MyClass" (see above).
+ * If c), then DrJava executes MyClass.main (traditional java behavior).
+ *
+ * @param s the command to be transformed
+ * @return the transformed command
+ */
+ public String transformRunCommand(String s) {
+ if (s.endsWith(";")) s = _deleteSemiColon(s);
+ List args = ArgumentTokenizer.tokenize(s, true);
+ final String classNameWithQuotes = args.get(1); // this is "MyClass"
+ final String className =
+ classNameWithQuotes.substring(1, classNameWithQuotes.length() - 1); // removes quotes, becomes MyClass
+
+ // we pass MyClass.class just to get a "Static Error: Undefined class 'MyClass'"
+ String ret = JavacCompiler.class.getName()+".runCommand(\""+s.toString()+"\", "+className+".class)";
+ // System.out.println(ret);
+ return ret;
+ }
+
+ /** Assumes a trimmed String. Returns a string of the call that the interpreter can use.
+ * The arguments get formatted as comma-separated list of strings enclosed in quotes.
+ * Example: _transformCommand("java MyClass arg1 arg2 arg3", "{0}.main(new String[]'{'{1}'}');")
+ * returns "MyClass.main(new String[]{\"arg1\",\"arg2\",\"arg3\"});"
+ * NOTE: the command to run is constructed using {@link java.text.MessageFormat}. That means that certain characters,
+ * single quotes and curly braces, for example, are special. To write single quotes, you need to double them.
+ * To write curly braces, you need to enclose them in single quotes. Example:
+ * MessageFormat.format("Abc {0} ''foo'' '{'something'}'", "def") returns "Abc def 'foo' {something}".
+ * @param s the command line, either "java MyApp arg1 arg2 arg3" or "applet MyApplet arg1 arg2 arg3"
+ * @param command the command to execute, with {0} marking the place for the class name and {1} the place for the arguments
+ * @return the transformed command
+ */
+ protected static String _transformCommand(String s, String command) {
+ if (s.endsWith(";")) s = _deleteSemiColon(s);
+ List args = ArgumentTokenizer.tokenize(s, true);
+ final String classNameWithQuotes = args.get(1); // this is "MyClass"
+ final String className = classNameWithQuotes.substring(1, classNameWithQuotes.length() - 1); // removes quotes, becomes MyClass
+ final StringBuilder argsString = new StringBuilder();
+ boolean seenArg = false;
+ for (int i = 2; i < args.size(); i++) {
+ if (seenArg) argsString.append(",");
+ else seenArg = true;
+ argsString.append(args.get(i));
+ }
+ return java.text.MessageFormat.format(command, className, argsString.toString());
+ }
+
+ /** Deletes the last character of a string. Assumes semicolon at the end, but does not check. Helper
+ * for _transformCommand(String,String).
+ * @param s the String containing the semicolon
+ * @return a substring of s with one less character
+ */
+ protected static String _deleteSemiColon(String s) { return s.substring(0, s.length() - 1); }
+
+// public boolean isSourceFileForThisCompiler(File f) {
+// if (f == null) return false;
+// String fileName = f.getName();
+// return fileName.endsWith(".java") || fileName.endsWith(".dj");
+// }
+
+ /** .java {@literal -->} true
+ * .dj {@literal -->} true
+ * .dj0 {@literal -->} true
+ * .dj1 {@literal -->} true
+ * .dj2 {@literal -->} true
+ * otherwise false
+ * @return true if the specified file is a source file for this compiler. */
+ public boolean isSourceFileForThisCompiler(File f) {
+ // by default, use DrJavaFileUtils.isSourceFile
+ return DrJavaFileUtils.isSourceFile(f);
+ }
+
+// public Set getSourceFileExtensions() {
+// HashSet extensions = new HashSet();
+// extensions.add("java");
+// return extensions;
+// }
+
+ /** Return the set of source file extensions that this compiler supports.
+ * @return the set of source file extensions that this compiler supports. */
+ public Set getSourceFileExtensions() { return DrJavaFileUtils.getSourceFileExtensions(); }
+
+// public String getSuggestedFileExtension() { return ".java"; }
+
+ /** Return the suggested file extension that will be appended to a file without extension.
+ * @return the suggested file extension */
+ public String getSuggestedFileExtension() { return DrJavaFileUtils.getSuggestedFileExtension(); }
+
+ /** Return a file filter that can be used to open files this compiler supports.
+ * @return file filter for appropriate source files for this compiler */
+ public FileFilter getFileFilter() { return new SmartSourceFilter(); }
+
+// public String getOpenAllFilesInFolderExtension() {
+// // Should we use OptionConstants for this?
+// return ".java";
+// }
+
+ /** Return the extension of the files that should be opened with the "Open Folder..." command.
+ * @return file extension for the "Open Folder..." command for this compiler. */
+ public String getOpenAllFilesInFolderExtension() {
+ return OptionConstants.LANGUAGE_LEVEL_EXTENSIONS[DrJava.getConfig().getSetting(OptionConstants.LANGUAGE_LEVEL)];
+ }
+
+ /** Return the set of keywords that should be highlighted in the specified file.
+ * @param f file for which to return the keywords
+ * @return the set of keywords that should be highlighted in the specified file. */
+ public Set getKeywordsForFile(File f) { return new HashSet<>(JAVA_KEYWORDS); }
+
+ /** Set of Java/GJ keywords for special coloring. */
+ public static final HashSet JAVA_KEYWORDS = new HashSet<>();
+ static {
+ final String[] words = {
+ "import", "native", "package", "goto", "const", "if", "else", "switch", "while", "for", "do", "true", "false",
+ "null", "this", "super", "new", "instanceof", "return", "static", "synchronized", "transient", "volatile",
+ "final", "strictfp", "throw", "try", "catch", "finally", "throws", "extends", "implements", "interface", "class",
+ "break", "continue", "public", "protected", "private", "abstract", "case", "default", "assert", "enum"
+ };
+ Collections.addAll(JAVA_KEYWORDS, words);
+ }
+
+ /** @return true since this compiler can be used in conjunction with the language level facility. */
+ public boolean supportsLanguageLevels() { return true; }
+}
\ No newline at end of file
diff --git a/drjava/src/edu/rice/cs/drjava/model/compiler/NoCompilerAvailable.java b/drjava/src/edu/rice/cs/drjava/model/compiler/NoCompilerAvailable.java
index cb4e02a77..fcc45e6d2 100644
--- a/drjava/src/edu/rice/cs/drjava/model/compiler/NoCompilerAvailable.java
+++ b/drjava/src/edu/rice/cs/drjava/model/compiler/NoCompilerAvailable.java
@@ -71,6 +71,8 @@ public List extends DJError> compile(List extends File> files, List extend
@Override
public String toString() { return "None"; }
+ /** A compiler can instruct DrJava to include additional elements for the boot
+ * class path of the Interactions JVM. This isn't necessary for the Java compilers, though. */
public List additionalBootClassPathForInteractions() { return Arrays.asList(); }
/** Transform the command line to be interpreted into something the Interactions JVM can use.
diff --git a/drjava/src/edu/rice/cs/drjava/model/junit/DefaultJUnitModel.java b/drjava/src/edu/rice/cs/drjava/model/junit/DefaultJUnitModel.java
index 3f934b1d1..d2cb78d3d 100644
--- a/drjava/src/edu/rice/cs/drjava/model/junit/DefaultJUnitModel.java
+++ b/drjava/src/edu/rice/cs/drjava/model/junit/DefaultJUnitModel.java
@@ -232,12 +232,11 @@ public void junit(OpenDefinitionsDocument doc) throws ClassNotFoundException, IO
debug.logEnd("junit(doc)");
}
- /** Ensures that all documents have been compiled since their last
- * modification and then delegates the actual testing to
- * _rawJUnitOpenTestDocs.
- * @param lod list of open documents
- * @param allTests true if all tests are to be run
- */
+ /** Ensures that all documents have been compiled since their last modification and then delegates the actual testing to
+ * _rawJUnitOpenTestDocs.
+ * @param lod list of open documents
+ * @param allTests true if all tests are to be run
+ */
private void junitOpenDefDocs(final List lod, final boolean allTests) {
// If a test is running, don't start another one.
@@ -409,7 +408,7 @@ private void _rawJUnitOpenDefDocs(List lod, final boole
try {
final Box className = new SimpleBox();
final Box sourceName = new SimpleBox();
- new ClassReader(IOUtil.toByteArray(entry)).accept(new ClassVisitor(Opcodes.ASM4) {
+ new ClassReader(IOUtil.toByteArray(entry)).accept(new ClassVisitor(Opcodes.ASM7) {
public void visit(int version, int access, String name, String sig, String sup, String[] inters) {
className.set(name.replace('/', '.'));
}
diff --git a/drjava/src/edu/rice/cs/drjava/model/junit/JUnitTestRunner.java b/drjava/src/edu/rice/cs/drjava/model/junit/JUnitTestRunner.java
index dfffa12a0..b3a805c05 100644
--- a/drjava/src/edu/rice/cs/drjava/model/junit/JUnitTestRunner.java
+++ b/drjava/src/edu/rice/cs/drjava/model/junit/JUnitTestRunner.java
@@ -34,8 +34,9 @@
import edu.rice.cs.util.Log;
import edu.rice.cs.util.UnexpectedException;
-/** DrJava's own testrunner. It updates the document in the JUnit pane as error and failure events are fired.
- * These methods run inan auxiliary thread.
+/** Runs in the InterpreterJVM. It uses RMI calls to update the the JUnitPanel as test results are reported. Some methods are
+ * synchronized to maintain the consistency of local state. These methods run in an auxiliary thread.
+ * GUI actions must be transferred to the event handling thread (DispatchThread).
* @version $Id$
*/
public class JUnitTestRunner extends BaseTestRunner {
@@ -56,8 +57,6 @@ public class JUnitTestRunner extends BaseTestRunner {
/** The current number of failures in the result. */
private int _failureCount;
-
-
/** Standard constructor.
* @param jmc a JUnitModelCallback
diff --git a/drjava/src/edu/rice/cs/drjava/model/repl/InteractionsModel.java b/drjava/src/edu/rice/cs/drjava/model/repl/InteractionsModel.java
index 9e5050d24..62cdf2e1c 100644
--- a/drjava/src/edu/rice/cs/drjava/model/repl/InteractionsModel.java
+++ b/drjava/src/edu/rice/cs/drjava/model/repl/InteractionsModel.java
@@ -685,7 +685,7 @@ public void interpreterResetting() {
if (! _waitingForFirstInterpreter) {
Utilities.invokeLater(new Runnable() {
public void run() {
- _document.insertBeforeLastPrompt(" Resetting Interactions ...\n", InteractionsDocument.ERROR_STYLE);
+ _document.insertBeforeLastPrompt(" Resetting Interactions and Clearing Console ...\n", InteractionsDocument.ERROR_STYLE);
_document.setInProgress(true);
}
});
diff --git a/drjava/src/edu/rice/cs/drjava/model/repl/newjvm/InterpreterJVM.java b/drjava/src/edu/rice/cs/drjava/model/repl/newjvm/InterpreterJVM.java
index c22d4373f..81b11f1a8 100644
--- a/drjava/src/edu/rice/cs/drjava/model/repl/newjvm/InterpreterJVM.java
+++ b/drjava/src/edu/rice/cs/drjava/model/repl/newjvm/InterpreterJVM.java
@@ -1,37 +1,46 @@
/*BEGIN_COPYRIGHT_BLOCK
*
- * Copyright (c) 2001-2019, JavaPLT group at Rice University (drjava@rice.edu). All rights reserved.
+ * Copyright (c) 2001-2017, JavaPLT group at Rice University (drjava@rice.edu)
+ * All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
- * following conditions are met:
- * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following
- * disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
- * following disclaimer in the documentation and/or other materials provided with the distribution.
- * * Neither the names of DrJava, the JavaPLT group, Rice University, nor the names of its contributors may be used
- * to endorse or promote products derived from this software without specific prior written permission.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
*
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * This software is Open Source Initiative approved Open Source Software. Open Source Initative Approved is a trademark
- * of the Open Source Initiative.
+ * This software is Open Source Initiative approved Open Source Software.
+ * Open Source Initative Approved is a trademark of the Open Source Initiative.
*
- * This file is part of DrJava. Download the current version of this project from http://www.drjava.org/ or
- * http://sourceforge.net/projects/drjava/
+ * This file is part of DrJava. Download the current version of this project
+ * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
*
* END_COPYRIGHT_BLOCK*/
+
package edu.rice.cs.drjava.model.repl.newjvm;
import java.util.*;
import java.io.*;
import java.rmi.*;
+import java.awt.EventQueue;
// NOTE: Do NOT import/use the config framework in this class!
// (This class runs in a different JVM, and will not share the config object)
@@ -61,8 +70,16 @@
import edu.rice.cs.dynamicjava.symbol.*;
import edu.rice.cs.dynamicjava.symbol.type.Type;
+//for JShell because dynamicJava does not have support for java9+
+import jdk.jshell.*;
+import java.util.List;
+import java.util.Locale;
+import java.util.stream.Collectors;
+import java.util.stream.StreamSupport;
+
// For Windows focus fix
import javax.swing.JDialog;
+import javax.tools.StandardLocation;
import static edu.rice.cs.plt.debug.DebugUtil.debug;
import static edu.rice.cs.plt.debug.DebugUtil.error;
@@ -78,8 +95,8 @@
* @version $Id$
*/
public class InterpreterJVM extends AbstractSlaveJVM implements InterpreterJVMRemoteI, JUnitModelCallback {
-
- public static final Log _log = new Log("GlobalModel.txt", false);
+ /** log for use in debugging */
+ public static final Log _log = new Log("InterpreterJVM.txt", false);
/** Singleton instance of this class. */
public static final InterpreterJVM ONLY = new InterpreterJVM();
@@ -92,11 +109,15 @@ public class InterpreterJVM extends AbstractSlaveJVM implements InterpreterJVMRe
private final Interpreter _defaultInterpreter;
private final Map _interpreters;
private final Set _busyInterpreters;
+ private final JShell _js;
// The following variable appears to be useless.
// private final Map> _environments;
private final ClassPathManager _classPathManager;
private final ClassLoader _interpreterLoader;
+ private StringBuilder output_buf;
+ private StringBuilder input_buf;
+ private int num_input_braces;
// Lock object for ensuring mutual exclusion on updates and compound accesses
private final Object _stateLock = new Object();
@@ -104,9 +125,10 @@ public class InterpreterJVM extends AbstractSlaveJVM implements InterpreterJVMRe
/** Responsible for running JUnit tests in this JVM. */
private final JUnitTestManager _junitTestManager;
+
/** Remote reference to the MainJVM class in DrJava's primary JVM. Assigned ONLY once. */
private volatile MainJVMRemoteI _mainJVM;
-
+
/** Private constructor; use the singleton ONLY instance. */
private InterpreterJVM() {
super("Reset Interactions Thread", "Poll DrJava Thread");
@@ -122,10 +144,35 @@ private InterpreterJVM() {
// _interpreterOptions = Options.DEFAULT;
_interpreterOptions = new InteractionsPaneOptions();
_defaultInterpreter = new Interpreter(_interpreterOptions, _interpreterLoader);
+// _defaultInterpreter =
_interpreters = new HashMap();
_busyInterpreters = new HashSet();
// _environments = new HashMap>();
_activeInterpreter = Pair.make("", _defaultInterpreter);
+
+ // Create a StringBuilder to capture the JShell Output
+ output_buf = new StringBuilder();
+ input_buf = new StringBuilder();
+ num_input_braces = 0;
+ // Create a PrintStream that will write to our StringBuilder
+ PrintStream printStream = new PrintStream(new OutputStream() {
+ @Override
+ public void write(int b) {
+ output_buf.append((char) b);
+ }
+ });
+
+ try {
+ _js = JShell.builder()
+ .out(printStream)
+ .err(printStream)
+ .compilerOptions("-classpath", getClassPathString())
+ .build();
+ } catch(IllegalStateException e) {
+ //Potentially exit system or try to create a new JShell instance
+ System.err.println("JShell is not available in this environment");
+ throw new RuntimeException(e);
+ }
}
/** Actions to perform when this JVM is started (through its superclass, AbstractSlaveJVM). Not synchronized
@@ -144,11 +191,12 @@ protected String _getInput() {
}
}
});
-
- // redirect stdout
+
System.setOut(new PrintStream(new OutputStreamRedirector() {
public void print(String s) {
- try { _mainJVM.systemOutPrint(s); }
+ try {
+ _mainJVM.systemOutPrint(s);
+ }
catch (RemoteException re) {
error.log(re);
throw new UnexpectedException("Main JVM can't be reached for output.\n" + re);
@@ -213,7 +261,9 @@ private boolean isBusyInterpreter(Interpreter i) {
* local state.
* @param s Source code to interpret.
*/
- public InterpretResult interpret(String s) { return interpret(s, _activeInterpreter.second()); }
+ public InterpretResult interpret(String s) {
+ return interpret(s, _activeInterpreter.second());
+ }
/** Interprets the given string of source code with the given interpreter. The result is returned to
* MainJVM via the interpretResult method.
@@ -229,48 +279,98 @@ public InterpretResult interpret(String s, String name) {
}
return interpret(s, i);
}
-
+
+ /**
+ * Interprets the given string of code with an instance of JShell and returns the result wrapped in a InterpretResult object
+ * Currently does NOT support differentiation between different types of results, only treats them as objects.
+ * Currently does NOT support printing of basic expressions, i.e. "2 + 2" will not print 4 (but it should)
+ * @param code - the code to be interpreted
+ * @return InterpretResult - the result of the interpretation
+ * @throws InterpreterException - in the case the JShell instance is not available or an error occurs during interpretation
+ */
+ private InterpretResult interpretWithJShell(StringBuilder input_buf) throws InterpreterException {
+ InterpretResult res = null;
+ //TD set verbosity level so it doesn't freak out over things like semicolons
+ if (_js == null) {
+ //TODO create InterpretResultException here
+ return InterpretResult.exception(new EvaluatorException(new Throwable("An error has occured that has caused the Interpreter to not be available.")));
+ }
+
+// System.out.println("Evalulating: " + input_buf.toString());
+ List events = _js.eval(input_buf.toString());
+ //getting rid of new line character at the end
+ if (output_buf.length() > 0 && output_buf.charAt(output_buf.length() - 1) == '\n') {
+ output_buf.setLength(output_buf.length() - 1);
+ }
+
+ boolean hasError = false;
+
+ //TODO Jshell adds a lot of fluff to the output, try and only get the cause of the error
+ for (SnippetEvent e : events) {
+ if (e.status() == Snippet.Status.REJECTED) {
+ Diag diagnostics = _js.diagnostics(e.snippet()).collect(Collectors.toList()).get(0);
+ output_buf.append(diagnostics.getMessage(Locale.getDefault()));
+ res = InterpretResult.exception(new EvaluatorException(new Throwable(output_buf.toString())));
+ hasError = true;
+ } else if (e.value() != null) {
+ output_buf.append(e.value()).append("\n");
+ }
+ }
+
+ if (!hasError && output_buf.length() > 0) {
+ // Remove the last newline character added
+ output_buf.setLength(output_buf.length() - 1);
+ res = InterpretResult.objectValue(output_buf.toString(), "JShellOutput");
+ }
+
+ if (res == null) {
+ //Setting InterpretResult as an object value rather than doing case work as JShell will internally keep track of state, bypassing need for us to do so
+ res = InterpretResult.objectValue(output_buf.toString(), "JShellOutput");
+ }
+
+ output_buf.setLength(0);
+ //clear input after setting multiple lines
+ input_buf.setLength(0);
+ return res;
+ }
+
private InterpretResult interpret(String input, Interpreter interpreter) {
- debug.logStart("Interpret " + input);
-
+// System.out.println("Received input: " + input);
boolean available = addBusyInterpreter(interpreter);
if (! available) { debug.logEnd(); return InterpretResult.busy(); }
-
+
// set the thread context class loader, this way NextGen and Mint can use the interpreter's class loader
Thread.currentThread().setContextClassLoader(_interpreterLoader); // _interpreterLoader is final
-
- Option