diff --git a/java/src/processing/mode/java/pdex/ASTGenerator.java b/java/src/processing/mode/java/pdex/ASTGenerator.java index 4269b013c..06f230ee4 100644 --- a/java/src/processing/mode/java/pdex/ASTGenerator.java +++ b/java/src/processing/mode/java/pdex/ASTGenerator.java @@ -290,7 +290,7 @@ public class ASTGenerator { return codeTree; } - protected ClassPathFactory factory; + protected ClassPathFactory factory = new ClassPathFactory(); /** * Used for searching for package declaration of a class @@ -298,58 +298,6 @@ public class ASTGenerator { protected ClassPath classPath; - /** - * Loads up .jar files and classes defined in it for completion lookup - */ - protected void loadJars() { - factory = new ClassPathFactory(); - - StringList entries = new StringList(); - entries.append(System.getProperty("java.class.path")); - entries.append(System.getProperty("java.home") + - File.separator + "lib" + File.separator + "rt.jar"); - - String modeClassPath = ((JavaMode) editor.getMode()).getSearchPath(); - if (modeClassPath != null) { - entries.append(modeClassPath); - } - - if (errorCheckerService.classpathJars != null) { - synchronized (errorCheckerService.classpathJars) { - for (URL jarPath : errorCheckerService.classpathJars) { - entries.append(jarPath.getPath()); - } - } - } - -// // Just in case, make sure we don't run off into oblivion -// String workingDirectory = System.getProperty("user.dir"); -// if (entries.removeValue(workingDirectory) != -1) { -// System.err.println("user.dir found in classpath"); -// } - -// // hm, these weren't problematic either -// entries.append(System.getProperty("user.dir")); -// entries.append(""); -// entries.print(); - - classPath = factory.createFromPath(entries.join(File.pathSeparator)); - log("Classpath created " + (classPath != null)); - log("Sketch classpath jars loaded."); - if (Platform.isMacOS()) { - File f = new File(System.getProperty("java.home") + - File.separator + "bundle" + - File.separator + "Classes" + - File.separator + "classes.jar"); - log(f.getAbsolutePath() + " | classes.jar found?" + f.exists()); - } else { - File f = new File(System.getProperty("java.home") + File.separator + - "lib" + File.separator + "rt.jar" + File.separator); - log(f.getAbsolutePath() + " | rt.jar found?" + f.exists()); - } - } - - protected TreeMap jdocMap; protected void loadJavaDoc() { diff --git a/java/src/processing/mode/java/pdex/ErrorCheckerService.java b/java/src/processing/mode/java/pdex/ErrorCheckerService.java index 5b32c91bd..b33d5f1cc 100644 --- a/java/src/processing/mode/java/pdex/ErrorCheckerService.java +++ b/java/src/processing/mode/java/pdex/ErrorCheckerService.java @@ -56,6 +56,7 @@ import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import processing.app.Library; import processing.app.Messages; +import processing.app.Platform; import processing.app.Preferences; import processing.app.Sketch; import processing.app.SketchCode; @@ -64,6 +65,7 @@ import processing.app.ui.Editor; import processing.app.ui.EditorStatus; import processing.app.ui.ErrorTable; import processing.core.PApplet; +import processing.data.StringList; import processing.mode.java.JavaMode; import processing.mode.java.JavaEditor; import processing.mode.java.preproc.PdePreprocessor; @@ -75,10 +77,10 @@ import processing.mode.java.preproc.PdePreprocessor; @SuppressWarnings("unchecked") public class ErrorCheckerService { - protected JavaEditor editor; + protected final JavaEditor editor; /** The amazing eclipse ast parser */ - protected ASTParser parser = ASTParser.newParser(AST.JLS8); + protected final ASTParser parser = ASTParser.newParser(AST.JLS8); /** * Used to indirectly stop the Error Checker Thread @@ -136,7 +138,7 @@ public class ErrorCheckerService { * Stores the current import statements in the program. Used to compare for * changed import statements and update classpath if needed. */ - protected ArrayList programImports; + protected ArrayList programImports = new ArrayList<>(); /** * List of imports when sketch was last checked. Used for checking for @@ -147,12 +149,12 @@ public class ErrorCheckerService { /** * List of import statements for any .jar files in the code folder. */ - protected ArrayList codeFolderImports = new ArrayList<>(); + protected final ArrayList codeFolderImports = new ArrayList<>(); /** * Teh Preprocessor */ - protected XQPreprocessor xqpreproc; + protected final XQPreprocessor xqpreproc; /** * Regexp for import statements. (Used from Processing source) @@ -175,7 +177,7 @@ public class ErrorCheckerService { private Thread errorCheckerThread; - private BlockingQueue requestQueue = new ArrayBlockingQueue<>(1); + private final BlockingQueue requestQueue = new ArrayBlockingQueue<>(1); private ScheduledExecutorService scheduler; private volatile ScheduledFuture scheduledUiUpdate = null; private volatile long nextUiUpdate = 0; @@ -438,7 +440,7 @@ public class ErrorCheckerService { // If imports have changed, reload classes with new classpath. if (loadCompClass) { classPath = new URL[classpathJars.size()]; - classpathJars.toArray(classPath); + classPath = classpathJars.toArray(classPath); compilationChecker = null; classLoader = null; @@ -677,7 +679,7 @@ public class ErrorCheckerService { } // Also add jars specified in mode's search path - String searchPath = ((JavaMode) getEditor().getMode()).getSearchPath(); + String searchPath = ((JavaMode) editor.getMode()).getSearchPath(); if (searchPath != null) { String[] modeJars = PApplet.split(searchPath, File.pathSeparatorChar); for (String mj : modeJars) { @@ -688,14 +690,56 @@ public class ErrorCheckerService { } } } - new Thread(new Runnable() { - @Override - public void run() { - synchronized (astGenerator) { - astGenerator.loadJars(); // update jar file for completion lookup - } + + for (Library lib : editor.getMode().coreLibraries) { + try { + classpathJars.add(new File(lib.getJarPath()).toURI().toURL()); + } catch (MalformedURLException e) { + e.printStackTrace(); } - }).start(); + } + + StringList entries = new StringList(); + entries.append(System.getProperty("java.class.path").split(File.pathSeparator)); + entries.append(System.getProperty("java.home") + + File.separator + "lib" + File.separator + "rt.jar"); + + String modeClassPath = ((JavaMode) editor.getMode()).getSearchPath(); + if (modeClassPath != null) { + entries.append(modeClassPath); + } + + for (URL jarPath : classpathJars) { + entries.append(jarPath.getPath()); + } + +// // Just in case, make sure we don't run off into oblivion +// String workingDirectory = System.getProperty("user.dir"); +// if (entries.removeValue(workingDirectory) != -1) { +// System.err.println("user.dir found in classpath"); +// } + +// // hm, these weren't problematic either +// entries.append(System.getProperty("user.dir")); +// entries.append(""); +// entries.print(); + + synchronized (astGenerator) { + astGenerator.classPath = astGenerator.factory.createFromPath(entries.join(File.pathSeparator)); + Messages.log("Classpath created " + (astGenerator.classPath != null)); + Messages.log("Sketch classpath jars loaded."); + if (Platform.isMacOS()) { + File f = new File(System.getProperty("java.home") + + File.separator + "bundle" + + File.separator + "Classes" + + File.separator + "classes.jar"); + Messages.log(f.getAbsolutePath() + " | classes.jar found?" + f.exists()); + } else { + File f = new File(System.getProperty("java.home") + File.separator + + "lib" + File.separator + "rt.jar" + File.separator); + Messages.log(f.getAbsolutePath() + " | rt.jar found?" + f.exists()); + } + } } @@ -1058,7 +1102,7 @@ public class ErrorCheckerService { * code is not yet compile ready. */ protected String preprocessCode() { - programImports = new ArrayList<>(); + ArrayList scrappedImports = new ArrayList<>(); StringBuilder rawCode = new StringBuilder(); final Sketch sketch = editor.getSketch(); try { @@ -1068,10 +1112,12 @@ public class ErrorCheckerService { try { if (sketch.getCurrentCode().equals(sc)) { rawCode.append(scrapImportStatements(sc.getDocumentText(), - sketch.getCodeIndex(sc))); + sketch.getCodeIndex(sc), + scrappedImports)); } else { rawCode.append(scrapImportStatements(sc.getProgram(), - sketch.getCodeIndex(sc))); + sketch.getCodeIndex(sc), + scrappedImports)); } rawCode.append('\n'); } catch (Exception e) { @@ -1084,6 +1130,11 @@ public class ErrorCheckerService { } catch (Exception e) { Messages.log("Exception in preprocessCode()"); } + + // Swap atomically, might blow up anyway + // TODO: this is iterated from multiple threads, synchronize properly + this.programImports = scrappedImports; + String sourceAlt = rawCode.toString(); // Replace comments with whitespaces // sourceAlt = scrubComments(sourceAlt); @@ -1133,8 +1184,7 @@ public class ErrorCheckerService { checkForChangedImports(); - className = (editor == null) ? - "DefaultClass" : editor.getSketch().getName(); + className = editor.getSketch().getName(); // Check whether the code is being written in STATIC mode try { @@ -1148,7 +1198,7 @@ public class ErrorCheckerService { StringBuilder sb = new StringBuilder(); // Imports - sb.append(xqpreproc.prepareImports(programImports)); + sb.append(xqpreproc.prepareImports(scrappedImports)); // Header if (mode != PdePreprocessor.Mode.JAVA) { @@ -1335,7 +1385,9 @@ public class ErrorCheckerService { * - index of the tab * @return String - Tab code with imports replaced with white spaces */ - protected String scrapImportStatements(String tabProgram, int tabNumber) { + protected String scrapImportStatements(String tabProgram, + int tabNumber, + List outImports) { //TODO: Commented out imports are still detected as main imports. pdeImportsCount = 0; String tabSource = tabProgram; @@ -1360,7 +1412,7 @@ public class ErrorCheckerService { // + Base.countLines(tabSource.substring(0, idx)) + " tab " // + tabNumber); int lineCount = Util.countLines(tabSource.substring(0, idx)); - programImports.add(new ImportStatement(piece, tabNumber, lineCount)); + outImports.add(new ImportStatement(piece, tabNumber, lineCount)); // Remove the import from the main program // Substitute with white spaces String whiteSpace = "";