@@ -51,12 +51,12 @@ public class CompilerCUSTOM {
5151 /**
5252 * Compile with ECJ. See http://j.mp/8paifz for documentation.
5353 *
54- * @param sketch Sketch object to be compiled, used for placing exceptions
54+ * @param data. sketch Sketch object to be compiled, used for placing exceptions
5555 * @param buildPath Where the temporary files live and will be built from.
5656 * @return true if successful.
5757 * @throws SketchException Only if there's a problem. Only then.
5858 */
59- static public boolean compile (JavaBuildCUSTOM build ) throws SketchException {
59+ static public boolean compileCUSTOM (JavaBuildCUSTOM build ) throws SketchException {
6060
6161 // This will be filled in if anyone gets angry
6262 SketchException exception = null ;
@@ -66,7 +66,14 @@ static public boolean compile(JavaBuildCUSTOM build) throws SketchException {
6666
6767 String [] commandCUSTOM = generateCommandCUSTOM (build );
6868
69- polyglot .main .Main .main (commandCUSTOM );
69+ polyglot .main .Main polyglotMain = new polyglot .main .Main ();
70+
71+ try {
72+ polyglotMain .start (commandCUSTOM , new ent .EntExtensionInfo ());
73+ } catch (polyglot .main .Main .TerminationException e ) {
74+ System .err .println (e .getMessage ());
75+ System .exit (1 );
76+ }
7077
7178 try {
7279 // Load errors into a local StringBuilder
@@ -305,6 +312,268 @@ public void close() { }
305312 return success ;
306313 }
307314
315+
316+ static public boolean compile (JavaBuildCUSTOM build ) throws SketchException {
317+
318+ // This will be filled in if anyone gets angry
319+ SketchException exception = null ;
320+ boolean success = false ;
321+
322+ String baseCommand [] = new String [] {
323+ "-g" ,
324+ "-Xemacs" ,
325+ //"-noExit", // not necessary for ecj
326+ "-source" , "1.7" ,
327+ "-target" , "1.7" ,
328+ "-encoding" , "utf8" ,
329+ "-classpath" , build .getClassPath (),
330+ "-nowarn" , // we're not currently interested in warnings (works in ecj)
331+ "-d" , build .getBinFolder ().getAbsolutePath () // output the classes in the buildPath
332+ };
333+ //PApplet.println(baseCommand);
334+
335+ String [] sourceFiles = Util .listFiles (build .getSrcFolder (), false , ".java" );
336+ String [] command = PApplet .concat (baseCommand , sourceFiles );
337+ //PApplet.println(command);
338+
339+ try {
340+ // Load errors into a local StringBuilder
341+ final StringBuilder errorBuffer = new StringBuilder ();
342+
343+ // Create single method dummy writer class to slurp errors from ecj
344+ Writer internalWriter = new Writer () {
345+ public void write (char [] buf , int off , int len ) {
346+ errorBuffer .append (buf , off , len );
347+ }
348+
349+ public void flush () { }
350+
351+ public void close () { }
352+ };
353+ // Wrap as a PrintWriter since that's what compile() wants
354+ PrintWriter writer = new PrintWriter (internalWriter );
355+
356+ //result = com.sun.tools.javac.Main.compile(command, writer);
357+
358+ PrintWriter outWriter = new PrintWriter (System .out );
359+
360+ // Version that's not dynamically loaded
361+ //CompilationProgress progress = null;
362+ //success = BatchCompiler.compile(command, outWriter, writer, progress);
363+
364+ // Version that *is* dynamically loaded. First gets the mode class loader
365+ // so that it can grab the compiler JAR files from it.
366+ ClassLoader loader = build .mode .getClassLoader ();
367+ try {
368+ Class <?> batchClass =
369+ Class .forName ("org.eclipse.jdt.core.compiler.batch.BatchCompiler" , false , loader );
370+ Class <?> progressClass =
371+ Class .forName ("org.eclipse.jdt.core.compiler.CompilationProgress" , false , loader );
372+ Class <?>[] compileArgs =
373+ new Class <?>[] { String [].class , PrintWriter .class , PrintWriter .class , progressClass };
374+ Method compileMethod = batchClass .getMethod ("compile" , compileArgs );
375+ success = (Boolean )
376+ compileMethod .invoke (null , new Object [] { command , outWriter , writer , null });
377+ } catch (Exception e ) {
378+ e .printStackTrace ();
379+ throw new SketchException ("Unknown error inside the compiler." );
380+ }
381+
382+ // Close out the stream for good measure
383+ writer .flush ();
384+ writer .close ();
385+
386+ BufferedReader reader =
387+ new BufferedReader (new StringReader (errorBuffer .toString ()));
388+ //System.err.println(errorBuffer.toString());
389+
390+ String line = null ;
391+ while ((line = reader .readLine ()) != null ) {
392+ //System.out.println("got line " + line); // debug
393+
394+ // get first line, which contains file name, line number,
395+ // and at least the first line of the error message
396+ String errorFormat = "([\\ w\\ d_]+.java):(\\ d+):\\ s*(.*):\\ s*(.*)\\ s*" ;
397+ String [] pieces = PApplet .match (line , errorFormat );
398+ //PApplet.println(pieces);
399+
400+ // if it's something unexpected, die and print the mess to the console
401+ if (pieces == null ) {
402+ exception = new SketchException ("Cannot parse error text: " + line );
403+ exception .hideStackTrace ();
404+ // Send out the rest of the error message to the console.
405+ System .err .println (line );
406+ while ((line = reader .readLine ()) != null ) {
407+ System .err .println (line );
408+ }
409+ break ;
410+ }
411+
412+ // translate the java filename and line number into a un-preprocessed
413+ // location inside a source file or tab in the environment.
414+ String dotJavaFilename = pieces [1 ];
415+ // Line numbers are 1-indexed from javac
416+ int dotJavaLineIndex = PApplet .parseInt (pieces [2 ]) - 1 ;
417+ String errorMessage = pieces [4 ];
418+
419+ exception = build .placeException (errorMessage ,
420+ dotJavaFilename ,
421+ dotJavaLineIndex );
422+
423+ if (exception == null ) {
424+ exception = new SketchException (errorMessage );
425+ }
426+
427+ String [] parts = null ;
428+
429+ if (errorMessage .startsWith ("The import " ) &&
430+ errorMessage .endsWith ("cannot be resolved" )) {
431+ // The import poo cannot be resolved
432+ //import poo.shoe.blah.*;
433+ //String what = errorMessage.substring("The import ".length());
434+ String [] m = PApplet .match (errorMessage , "The import (.*) cannot be resolved" );
435+ //what = what.substring(0, what.indexOf(' '));
436+ if (m != null ) {
437+ // System.out.println("'" + m[1] + "'");
438+ if (m [1 ].equals ("processing.xml" )) {
439+ exception .setMessage ("processing.xml no longer exists, this code needs to be updated for 2.0." );
440+ System .err .println ("The processing.xml library has been replaced " +
441+ "with a new 'XML' class that's built-in." );
442+ handleCrustyCode ();
443+
444+ } else {
445+ exception .setMessage ("The package " +
446+ "\u201C " + m [1 ] + "\u201D " +
447+ " does not exist. " +
448+ "You might be missing a library." );
449+ System .err .println ("Libraries must be " +
450+ "installed in a folder named 'libraries' " +
451+ "inside the sketchbook folder " +
452+ "(see the Preferences window)." );
453+ }
454+ }
455+
456+ } else if (errorMessage .endsWith ("cannot be resolved to a type" )) {
457+ // xxx cannot be resolved to a type
458+ //xxx c;
459+
460+ String what = errorMessage .substring (0 , errorMessage .indexOf (' ' ));
461+
462+ if (what .equals ("BFont" ) ||
463+ what .equals ("BGraphics" ) ||
464+ what .equals ("BImage" )) {
465+ exception .setMessage (what + " has been replaced with P" + what .substring (1 ));
466+ handleCrustyCode ();
467+
468+ } else {
469+ exception .setMessage ("Cannot find a class or type " +
470+ "named \u201C " + what + "\u201D " );
471+
472+ String suggestion = importSuggestions .get (what );
473+ if (suggestion != null ) {
474+ System .err .println ("You may need to add \" import " + suggestion + ";\" to the top of your sketch." );
475+ System .err .println ("To make sketches more portable, imports that are not part of the Processing API were removed in Processing 2." );
476+ System .err .println ("See the changes page for more information: https://github.com/processing/processing/wiki/Changes" );
477+ }
478+ }
479+
480+ } else if (errorMessage .endsWith ("cannot be resolved" )) {
481+ // xxx cannot be resolved
482+ //println(xxx);
483+
484+ String what = errorMessage .substring (0 , errorMessage .indexOf (' ' ));
485+
486+ if (what .equals ("LINE_LOOP" ) ||
487+ what .equals ("LINE_STRIP" )) {
488+ exception .setMessage ("LINE_LOOP and LINE_STRIP are not available, " +
489+ "please update your code." );
490+ handleCrustyCode ();
491+
492+ } else if (what .equals ("framerate" )) {
493+ exception .setMessage ("framerate should be changed to frameRate." );
494+ handleCrustyCode ();
495+
496+ } else if (what .equals ("screen" )) {
497+ exception .setMessage ("Change screen.width and screen.height to " +
498+ "displayWidth and displayHeight." );
499+ handleCrustyCode ();
500+
501+ } else if (what .equals ("screenWidth" ) ||
502+ what .equals ("screenHeight" )) {
503+ exception .setMessage ("Change screenWidth and screenHeight to " +
504+ "displayWidth and displayHeight." );
505+ handleCrustyCode ();
506+
507+ } else {
508+ exception .setMessage ("Cannot find anything " +
509+ "named \u201C " + what + "\u201D " );
510+ }
511+
512+ } else if (errorMessage .startsWith ("Duplicate" )) {
513+ // "Duplicate nested type xxx"
514+ // "Duplicate local variable xxx"
515+
516+ } else if (null != (parts = PApplet .match (errorMessage ,
517+ "literal (\\ S*) of type (\\ S*) is out of range" ))) {
518+ if ("int" .equals (parts [2 ])) {
519+ exception .setMessage ("The type int can't handle numbers that big. Try "
520+ + parts [1 ] + "L to upgrade to long." );
521+ } else {
522+ // I'd like to give an essay on BigInteger and BigDecimal, but
523+ // this margin is too narrow to contain it.
524+ exception .setMessage ("Even the type " + parts [2 ] + " can't handle "
525+ + parts [1 ] + ". Research big numbers in Java." );
526+ }
527+ } else {
528+ // The method xxx(String) is undefined for the type Temporary_XXXX_XXXX
529+ //xxx("blah");
530+ // The method xxx(String, int) is undefined for the type Temporary_XXXX_XXXX
531+ //xxx("blah", 34);
532+ // The method xxx(String, int) is undefined for the type PApplet
533+ //PApplet.sub("ding");
534+ String undefined =
535+ "The method (\\ S+\\ (.*\\ )) is undefined for the type (.*)" ;
536+ parts = PApplet .match (errorMessage , undefined );
537+ if (parts != null ) {
538+ if (parts [1 ].equals ("framerate(int)" )) {
539+ exception .setMessage ("framerate() no longer exists, use frameRate() instead." );
540+ handleCrustyCode ();
541+
542+ } else if (parts [1 ].equals ("push()" )) {
543+ exception .setMessage ("push() no longer exists, use pushMatrix() instead." );
544+ handleCrustyCode ();
545+
546+ } else if (parts [1 ].equals ("pop()" )) {
547+ exception .setMessage ("pop() no longer exists, use popMatrix() instead." );
548+ handleCrustyCode ();
549+
550+ } else {
551+ String mess = "The function " + parts [1 ] + " does not exist." ;
552+ exception .setMessage (mess );
553+ }
554+ break ;
555+ }
556+ }
557+ if (exception != null ) {
558+ // The stack trace just shows that this happened inside the compiler,
559+ // which is a red herring. Don't ever show it for compiler stuff.
560+ exception .hideStackTrace ();
561+ break ;
562+ }
563+ }
564+ } catch (IOException e ) {
565+ String bigSigh = "Error while compiling. (" + e .getMessage () + ")" ;
566+ exception = new SketchException (bigSigh );
567+ e .printStackTrace ();
568+ success = false ;
569+ }
570+ // In case there was something else.
571+ if (exception != null ) throw exception ;
572+
573+ return success ;
574+ }
575+
576+
308577
309578private static String [] generateCommand (JavaBuildCUSTOM build ) {
310579 String baseCommand [] = new String [] {
@@ -330,7 +599,7 @@ private static String[] generateCommand(JavaBuildCUSTOM build) {
330599
331600private static String [] generateCommandCUSTOM (JavaBuildCUSTOM build ) {
332601
333- String sketchPath = "/Users/christianluetticke/Documents/processing/java/src/test/source/Sketch.pde" ;
602+ File expectedFolder = new File ( "/Users/christianluetticke/Documents/processing/java/src/test/output/" ) ;
334603
335604 String baseCommand [] = new String [] {
336605 "-g" ,
@@ -340,11 +609,14 @@ private static String[] generateCommandCUSTOM(JavaBuildCUSTOM build) {
340609 };
341610 PApplet .println (baseCommand );
342611
343- String [] sourceFiles = Util .listFiles (build .getSrcFolder (), false , ".java" );
612+ //String[] sourceFiles = Util.listFiles(build.getSrcFolder(), false, ".java");
613+ //PApplet.println("build.getSrcFolder(): " + build.getSrcFolder());
614+
615+ String [] sourceFiles = Util .listFiles (expectedFolder , false , ".java" );
616+ PApplet .println ("build.getSrcFolder(): " + build .getSrcFolder ());
617+
344618 String [] command = PApplet .concat (baseCommand , sourceFiles );
345- //PApplet.println(command);
346- PApplet .println (command );
347- return command ;
619+ return command ;
348620}
349621
350622 static protected void handleCrustyCode () {
0 commit comments