Package quarkninja.mode.xqmode

Source Code of quarkninja.mode.xqmode.XQCompiler

/*
  Part of the XQMode project - https://github.com/Manindra29/XQMode
 
  Under Google Summer of Code 2012 -
  http://www.google-melange.com/gsoc/homepage/google/gsoc2012
 
  Copyright (C) 2012 Manindra Moharana
 
  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License version 2
  as published by the Free Software Foundation.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software Foundation,
  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

package quarkninja.mode.xqmode;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.Writer;

import org.eclipse.jdt.core.compiler.CompilationProgress;
import org.eclipse.jdt.core.compiler.batch.BatchCompiler;

import processing.app.Base;
import processing.app.SketchException;
import processing.core.PApplet;
import processing.mode.java.JavaEditor;

/**
* This class is copied as it is from processing.mode.java.Compiler. This was
* needed so that it can access the required JDT jar files that have been class
* loaded along with XQMode.
*
* @author Manindra Moharana <mkmoharana29@gmail.com>
*/
public class XQCompiler extends processing.mode.java.Compiler {

  // public Compiler() { }

  /**
   * Compile with ECJ. See http://j.mp/8paifz for documentation.
   *
   * @param sketch
   *            Sketch object to be compiled, used for placing exceptions
   * @param buildPath
   *            Where the temporary files live and will be built from.
   * @return true if successful.
   * @throws RunnerException
   *             Only if there's a problem. Only then.
   */
  // public boolean compile(Sketch sketch,
  // File srcFolder,
  // File binFolder,
  // String primaryClassName,
  // String sketchClassPath,
  // String bootClassPath) throws RunnerException {
  static public boolean compile(XQJavaBuild build) throws SketchException {

    // This will be filled in if anyone gets angry
    SketchException exception = null;
    boolean success = false;

    String baseCommand[] = new String[] { "-Xemacs",
        // "-noExit", // not necessary for ecj
        "-source", "1.5", "-target", "1.5", "-classpath",
        build.getClassPath(), "-nowarn", // we're not currently
                          // interested in warnings
                          // (works in ecj)
        "-d", build.getBinFolder().getAbsolutePath() // output the
                                // classes in
                                // the buildPath
    };
    // PApplet.println(baseCommand);

    // make list of code files that need to be compiled
    // String[] sourceFiles = new String[sketch.getCodeCount()];
    // int sourceCount = 0;
    // sourceFiles[sourceCount++] =
    // new File(buildPath, primaryClassName + ".java").getAbsolutePath();
    //
    // for (SketchCode code : sketch.getCode()) {
    // if (code.isExtension("java")) {
    // String path = new File(buildPath,
    // code.getFileName()).getAbsolutePath();
    // sourceFiles[sourceCount++] = path;
    // }
    // }
    String[] sourceFiles = Base.listFiles(build.getSrcFolder(), false,
        ".java");

    // String[] command = new String[baseCommand.length +
    // sourceFiles.length];
    // System.arraycopy(baseCommand, 0, command, 0, baseCommand.length);
    // // append each of the files to the command string
    // System.arraycopy(sourceFiles, 0, command, baseCommand.length,
    // sourceCount);
    String[] command = PApplet.concat(baseCommand, sourceFiles);

    // PApplet.println(command);

    try {
      // Load errors into a local StringBuffer
      final StringBuffer errorBuffer = new StringBuffer();

      // Create single method dummy writer class to slurp errors from ecj
      Writer internalWriter = new Writer() {
        public void write(char[] buf, int off, int len) {
          errorBuffer.append(buf, off, len);
        }

        public void flush() {
        }

        public void close() {
        }
      };
      // Wrap as a PrintWriter since that's what compile() wants
      PrintWriter writer = new PrintWriter(internalWriter);

      // result = com.sun.tools.javac.Main.compile(command, writer);

      CompilationProgress progress = null;
      PrintWriter outWriter = new PrintWriter(System.out);
      success = BatchCompiler.compile(command, outWriter, writer,
          progress);
      // Close out the stream for good measure
      writer.flush();
      writer.close();

      BufferedReader reader = new BufferedReader(new StringReader(
          errorBuffer.toString()));
      // System.err.println(errorBuffer.toString());

      String line = null;
      while ((line = reader.readLine()) != null) {
        // System.out.println("got line " + line); // debug

        // get first line, which contains file name, line number,
        // and at least the first line of the error message
        String errorFormat = "([\\w\\d_]+.java):(\\d+):\\s*(.*):\\s*(.*)\\s*";
        String[] pieces = PApplet.match(line, errorFormat);
        // PApplet.println(pieces);

        // if it's something unexpected, die and print the mess to the
        // console
        if (pieces == null) {
          exception = new SketchException("Cannot parse error text: "
              + line);
          exception.hideStackTrace();
          // Send out the rest of the error message to the console.
          System.err.println(line);
          while ((line = reader.readLine()) != null) {
            System.err.println(line);
          }
          break;
        }

        // translate the java filename and line number into a
        // un-preprocessed
        // location inside a source file or tab in the environment.
        String dotJavaFilename = pieces[1];
        // Line numbers are 1-indexed from javac
        int dotJavaLineIndex = PApplet.parseInt(pieces[2]) - 1;
        String errorMessage = pieces[4];

        exception = build.placeException(errorMessage, dotJavaFilename,
            dotJavaLineIndex);
        /*
         * int codeIndex = 0; //-1; int codeLine = -1;
         *
         * // first check to see if it's a .java file for (int i = 0; i
         * < sketch.getCodeCount(); i++) { SketchCode code =
         * sketch.getCode(i); if (code.isExtension("java")) { if
         * (dotJavaFilename.equals(code.getFileName())) { codeIndex = i;
         * codeLine = dotJavaLineIndex; } } }
         *
         * // if it's not a .java file, codeIndex will still be 0 if
         * (codeIndex == 0) { // main class, figure out which tab //for
         * (int i = 1; i < sketch.getCodeCount(); i++) { for (int i = 0;
         * i < sketch.getCodeCount(); i++) { SketchCode code =
         * sketch.getCode(i);
         *
         * if (code.isExtension("pde")) { if (code.getPreprocOffset() <=
         * dotJavaLineIndex) { codeIndex = i;
         * //System.out.println("i'm thinkin file " + i); codeLine =
         * dotJavaLineIndex - code.getPreprocOffset(); } } } }
         * //System.out.println("code line now " + codeLine); exception
         * = new RunnerException(errorMessage, codeIndex, codeLine, -1,
         * false);
         */

        if (exception == null) {
          exception = new SketchException(errorMessage);
        }

        // for a test case once message parsing is implemented,
        // use new Font(...) since that wasn't getting picked up
        // properly.

        /*
         * if (errorMessage.equals("cannot find symbol")) {
         * handleCannotFindSymbol(reader, exception);
         *
         * } else if (errorMessage.indexOf("is already defined") != -1)
         * { reader.readLine(); // repeats the line of code w/ error int
         * codeColumn = caretColumn(reader.readLine()); exception = new
         * RunnerException(errorMessage, codeIndex, codeLine,
         * codeColumn);
         *
         * } else if (errorMessage.startsWith("package") &&
         * errorMessage.endsWith("does not exist")) { // Because imports
         * are stripped out and re-added to the 0th line of // the
         * preprocessed code, codeLine will always be wrong for imports.
         * exception = new RunnerException("P" +
         * errorMessage.substring(1) +
         * ". You might be missing a library."); } else { exception =
         * new RunnerException(errorMessage); }
         */
        if (errorMessage.startsWith("The import ")
            && errorMessage.endsWith("cannot be resolved")) {
          // The import poo cannot be resolved
          // import poo.shoe.blah.*;
          // String what =
          // errorMessage.substring("The import ".length());
          String[] m = PApplet.match(errorMessage,
              "The import (.*) cannot be resolved");
          // what = what.substring(0, what.indexOf(' '));
          if (m != null) {
            // System.out.println("'" + m[1] + "'");
            if (m[1].equals("processing.xml")) {
              exception
                  .setMessage("processing.xml no longer exists, this code needs to be updated for 2.0.");
              System.err
                  .println("The processing.xml library has been replaced "
                      + "with a new 'XML' class that's built-in.");
              handleCrustyCode();

            } else {
              exception.setMessage("The package " + "\u201C"
                  + m[1] + "\u201D" + " does not exist. "
                  + "You might be missing a library.");
              System.err
                  .println("Libraries must be "
                      + "installed in a folder named 'libraries' "
                      + "inside the 'sketchbook' folder.");
            }
          }

          // // Actually create the folder and open it for the user
          // File sketchbookLibraries =
          // Base.getSketchbookLibrariesFolder();
          // if (!sketchbookLibraries.exists()) {
          // if (sketchbookLibraries.mkdirs()) {
          // Base.openFolder(sketchbookLibraries);
          // }
          // }

        } else if (errorMessage
            .endsWith("cannot be resolved to a type")) {
          // xxx cannot be resolved to a type
          // xxx c;

          String what = errorMessage.substring(0,
              errorMessage.indexOf(' '));

          if (what.equals("BFont") || what.equals("BGraphics")
              || what.equals("BImage")) {
            exception.setMessage(what + " has been replaced with P"
                + what.substring(1));
            handleCrustyCode();

          } else {
            exception.setMessage("Cannot find a class or type "
                + "named \u201C" + what + "\u201D");
          }

        } else if (errorMessage.endsWith("cannot be resolved")) {
          // xxx cannot be resolved
          // println(xxx);

          String what = errorMessage.substring(0,
              errorMessage.indexOf(' '));

          if (what.equals("LINE_LOOP") || what.equals("LINE_STRIP")) {
            exception
                .setMessage("LINE_LOOP and LINE_STRIP are not available, "
                    + "please update your code.");
            handleCrustyCode();

          } else if (what.equals("framerate")) {
            exception
                .setMessage("framerate should be changed to frameRate.");
            handleCrustyCode();

          } else if (what.equals("screen")) {
            exception
                .setMessage("Change screen.width and screen.height to "
                    + "displayWidth and displayHeight.");
            handleCrustyCode();

          } else if (what.equals("screenWidth")
              || what.equals("screenHeight")) {
            exception
                .setMessage("Change screenWidth and screenHeight to "
                    + "displayWidth and displayHeight.");
            handleCrustyCode();

          } else {
            exception.setMessage("Cannot find anything "
                + "named \u201C" + what + "\u201D");
          }

        } else if (errorMessage.startsWith("Duplicate")) {
          // "Duplicate nested type xxx"
          // "Duplicate local variable xxx"

        } else {
          String[] parts = null;

          // The method xxx(String) is undefined for the type
          // Temporary_XXXX_XXXX
          // xxx("blah");
          // The method xxx(String, int) is undefined for the type
          // Temporary_XXXX_XXXX
          // xxx("blah", 34);
          // The method xxx(String, int) is undefined for the type
          // PApplet
          // PApplet.sub("ding");
          String undefined = "The method (\\S+\\(.*\\)) is undefined for the type (.*)";
          parts = PApplet.match(errorMessage, undefined);
          if (parts != null) {
            if (parts[1].equals("framerate(int)")) {
              exception
                  .setMessage("framerate() no longer exists, use frameRate() instead.");
              handleCrustyCode();

            } else if (parts[1].equals("push()")) {
              exception
                  .setMessage("push() no longer exists, use pushMatrix() instead.");
              handleCrustyCode();

            } else if (parts[1].equals("pop()")) {
              exception
                  .setMessage("pop() no longer exists, use popMatrix() instead.");
              handleCrustyCode();

            } else {
              String mess = "The function " + parts[1]
                  + " does not exist.";
              exception.setMessage(mess);
            }
            break;
          }
        }
        if (exception != null) {
          // The stack trace just shows that this happened inside the
          // compiler,
          // which is a red herring. Don't ever show it for compiler
          // stuff.
          exception.hideStackTrace();
          break;
        }
      }
    } catch (IOException e) {
      String bigSigh = "Error while compiling. (" + e.getMessage() + ")";
      exception = new SketchException(bigSigh);
      e.printStackTrace();
      success = false;
    }
    // In case there was something else.
    if (exception != null)
      throw exception;

    return success;
  }

  static protected void handleCrustyCode() {
    System.err.println("This code needs to be updated "
        + "for this version of Processing, "
        + "please read the Changes page on the Wiki.");
    JavaEditor.showChanges();
  }

  protected int caretColumn(String caretLine) {
    return caretLine.indexOf("^");
  }
}
TOP

Related Classes of quarkninja.mode.xqmode.XQCompiler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.