Search in sources :

Example 1 with PreprocessorResult

use of processing.mode.java.preproc.PreprocessorResult in project processing by processing.

the class JavaBuild method preprocess.

/**
   * @param srcFolder location where the .java source files will be placed
   * @param packageName null, or the package name that should be used as default
   * @param preprocessor the preprocessor object ready to do the work
   * @return main PApplet class name found during preprocess, or null if error
   * @throws SketchException
   */
public String preprocess(File srcFolder, String packageName, PdePreprocessor preprocessor, boolean sizeWarning) throws SketchException {
    // make sure the user isn't playing "hide the sketch folder"
    sketch.ensureExistence();
    //    System.out.println("srcFolder is " + srcFolder);
    classPath = binFolder.getAbsolutePath();
    // figure out the contents of the code folder to see if there
    // are files that need to be added to the imports
    StringList codeFolderPackages = null;
    if (sketch.hasCodeFolder()) {
        File codeFolder = sketch.getCodeFolder();
        javaLibraryPath = codeFolder.getAbsolutePath();
        // get a list of .jar files in the "code" folder
        // (class files in subfolders should also be picked up)
        String codeFolderClassPath = Util.contentsToClassPath(codeFolder);
        // append the jar files in the code folder to the class path
        classPath += File.pathSeparator + codeFolderClassPath;
        // get list of packages found in those jars
        codeFolderPackages = Util.packageListFromClassPath(codeFolderClassPath);
    } else {
        javaLibraryPath = "";
    }
    // 1. concatenate all .pde files to the 'main' pde
    //    store line number for starting point of each code bit
    StringBuilder bigCode = new StringBuilder();
    int bigCount = 0;
    for (SketchCode sc : sketch.getCode()) {
        if (sc.isExtension("pde")) {
            sc.setPreprocOffset(bigCount);
            bigCode.append(sc.getProgram());
            bigCode.append('\n');
            bigCount += sc.getLineCount();
        }
    }
    // initSketchSize() sets the internal sketchWidth/Height/Renderer vars
    // in the preprocessor. Those are used in preproc.write() so that they
    // can be used to add methods (settings() or sketchXxxx())
    //String[] sizeParts =
    SurfaceInfo sizeInfo = preprocessor.initSketchSize(sketch.getMainProgram(), sizeWarning);
    if (sizeInfo == null) {
        // An error occurred while trying to pull out the size, so exit here
        return null;
    }
    // by writeFooter() when it emits the settings() method.
    if (sizeInfo != null && sizeInfo.hasSettings()) {
        //      String sizeStatement = sizeInfo.getStatement();
        for (String stmt : sizeInfo.getStatements()) {
            //System.out.format("size stmt is '%s'%n", sizeStatement);
            // Don't remove newlines (and while you're at it, just keep spaces)
            // https://github.com/processing/processing/issues/3654
            stmt = stmt.trim();
            int index = bigCode.indexOf(stmt);
            if (index != -1) {
                bigCode.delete(index, index + stmt.length());
            } else {
                // TODO remove once we hit final; but prevent an exception like in
                // https://github.com/processing/processing/issues/3531
                System.err.format("Error removing '%s' from the code.", stmt);
            }
        }
    }
    PreprocessorResult result;
    try {
        File outputFolder = (packageName == null) ? srcFolder : new File(srcFolder, packageName.replace('.', '/'));
        outputFolder.mkdirs();
        //      Base.openFolder(outputFolder);
        final File java = new File(outputFolder, sketch.getName() + ".java");
        final PrintWriter stream = new PrintWriter(new FileWriter(java));
        try {
            result = preprocessor.write(stream, bigCode.toString(), codeFolderPackages);
        } finally {
            stream.close();
        }
    } catch (FileNotFoundException fnfe) {
        fnfe.printStackTrace();
        String msg = "Build folder disappeared or could not be written";
        throw new SketchException(msg);
    } catch (antlr.RecognitionException re) {
        // re also returns a column that we're not bothering with for now
        // first assume that it's the main file
        //      int errorFile = 0;
        int errorLine = re.getLine() - 1;
        // then search through for anyone else whose preprocName is null,
        // since they've also been combined into the main pde.
        int errorFile = findErrorFile(errorLine);
        //      System.out.println("error line is " + errorLine + ", file is " + errorFile);
        errorLine -= sketch.getCode(errorFile).getPreprocOffset();
        //      System.out.println("  preproc offset for that file: " + sketch.getCode(errorFile).getPreprocOffset());
        //      System.out.println("i found this guy snooping around..");
        //      System.out.println("whatcha want me to do with 'im boss?");
        //      System.out.println(errorLine + " " + errorFile + " " + code[errorFile].getPreprocOffset());
        String msg = re.getMessage();
        if (msg.contains("expecting RCURLY")) {
            // useful for other similar situations).
            throw new SketchException("Found one too many { characters " + "without a } to match it.", errorFile, errorLine, re.getColumn(), false);
        }
        if (msg.contains("expecting LCURLY")) {
            System.err.println(msg);
            String suffix = ".";
            String[] m = PApplet.match(msg, "found ('.*')");
            if (m != null) {
                suffix = ", not " + m[1] + ".";
            }
            throw new SketchException("Was expecting a { character" + suffix, errorFile, errorLine, re.getColumn(), false);
        }
        if (msg.indexOf("expecting RBRACK") != -1) {
            System.err.println(msg);
            throw new SketchException("Syntax error, " + "maybe a missing ] character?", errorFile, errorLine, re.getColumn(), false);
        }
        if (msg.indexOf("expecting SEMI") != -1) {
            System.err.println(msg);
            throw new SketchException("Syntax error, " + "maybe a missing semicolon?", errorFile, errorLine, re.getColumn(), false);
        }
        if (msg.indexOf("expecting RPAREN") != -1) {
            System.err.println(msg);
            throw new SketchException("Syntax error, " + "maybe a missing right parenthesis?", errorFile, errorLine, re.getColumn(), false);
        }
        if (msg.indexOf("preproc.web_colors") != -1) {
            throw new SketchException("A web color (such as #ffcc00) " + "must be six digits.", errorFile, errorLine, re.getColumn(), false);
        }
        //System.out.println("msg is " + msg);
        throw new SketchException(msg, errorFile, errorLine, re.getColumn(), false);
    } catch (antlr.TokenStreamRecognitionException tsre) {
        // while this seems to store line and column internally,
        // there doesn't seem to be a method to grab it..
        // so instead it's done using a regexp
        //      System.err.println("and then she tells me " + tsre.toString());
        // TODO not tested since removing ORO matcher.. ^ could be a problem
        String mess = "^line (\\d+):(\\d+):\\s";
        String[] matches = PApplet.match(tsre.toString(), mess);
        if (matches != null) {
            int errorLine = Integer.parseInt(matches[1]) - 1;
            int errorColumn = Integer.parseInt(matches[2]);
            int errorFile = 0;
            for (int i = 1; i < sketch.getCodeCount(); i++) {
                SketchCode sc = sketch.getCode(i);
                if (sc.isExtension("pde") && (sc.getPreprocOffset() < errorLine)) {
                    errorFile = i;
                }
            }
            errorLine -= sketch.getCode(errorFile).getPreprocOffset();
            throw new SketchException(tsre.getMessage(), errorFile, errorLine, errorColumn);
        } else {
            // this is bad, defaults to the main class.. hrm.
            String msg = tsre.toString();
            throw new SketchException(msg, 0, -1, -1);
        }
    } catch (SketchException pe) {
        // get lost in the more general "Exception" handler below.
        throw pe;
    } catch (Exception ex) {
        // TODO better method for handling this?
        System.err.println("Uncaught exception type:" + ex.getClass());
        ex.printStackTrace();
        throw new SketchException(ex.toString());
    }
    // grab the imports from the code just preprocessed
    importedLibraries = new ArrayList<Library>();
    Library core = mode.getCoreLibrary();
    if (core != null) {
        importedLibraries.add(core);
        classPath += core.getClassPath();
        javaLibraryPath += File.pathSeparator + core.getNativePath();
    }
    //    System.out.println("extra imports: " + result.extraImports);
    for (String item : result.extraImports) {
        //      System.out.println("item = '" + item + "'");
        // remove things up to the last dot
        int dot = item.lastIndexOf('.');
        // http://dev.processing.org/bugs/show_bug.cgi?id=1145
        String entry = (dot == -1) ? item : item.substring(0, dot);
        if (item.startsWith("static ")) {
            // import static - https://github.com/processing/processing/issues/8
            // Remove more stuff.
            int dot2 = item.lastIndexOf('.');
            entry = entry.substring(7, (dot2 == -1) ? entry.length() : dot2);
        //        System.out.println(entry);
        }
        //      System.out.println("library searching for " + entry);
        Library library = mode.getLibrary(entry);
        if (library != null) {
            if (!importedLibraries.contains(library)) {
                importedLibraries.add(library);
                classPath += library.getClassPath();
                javaLibraryPath += File.pathSeparator + library.getNativePath();
            }
        } else {
            boolean found = false;
            // import, don't show an error for it.
            if (codeFolderPackages != null) {
                String itemPkg = entry;
                for (String pkg : codeFolderPackages) {
                    if (pkg.equals(itemPkg)) {
                        found = true;
                        break;
                    }
                }
            }
            if (ignorableImport(entry + '.')) {
                found = true;
            }
            if (!found) {
                System.err.println("No library found for " + entry);
            }
        }
    }
    //    PApplet.println(PApplet.split(libraryPath, File.pathSeparatorChar));
    // Finally, add the regular Java CLASSPATH. This contains everything
    // imported by the PDE itself (core.jar, pde.jar, quaqua.jar) which may
    // in fact be more of a problem.
    String javaClassPath = System.getProperty("java.class.path");
    // Remove quotes if any.. A messy (and frequent) Windows problem
    if (javaClassPath.startsWith("\"") && javaClassPath.endsWith("\"")) {
        javaClassPath = javaClassPath.substring(1, javaClassPath.length() - 1);
    }
    classPath += File.pathSeparator + javaClassPath;
    for (SketchCode sc : sketch.getCode()) {
        if (sc.isExtension("java")) {
            // In most cases, no pre-processing services necessary for Java files.
            // Just write the the contents of 'program' to a .java file
            // into the build directory. However, if a default package is being
            // used (as in Android), and no package is specified in the source,
            // then we need to move this code to the same package as the sketch.
            // Otherwise, the class may not be found, or at a minimum, the default
            // access across the packages will mean that things behave incorrectly.
            // For instance, desktop code that uses a .java file with no packages,
            // will be fine with the default access, but since Android's PApplet
            // requires a package, code from that (default) package (such as the
            // PApplet itself) won't have access to methods/variables from the
            // package-less .java file (unless they're all marked public).
            String filename = sc.getFileName();
            try {
                String javaCode = sc.getProgram();
                String[] packageMatch = PApplet.match(javaCode, PACKAGE_REGEX);
                if (packageMatch == null && packageName == null) {
                    sc.copyTo(new File(srcFolder, filename));
                } else {
                    if (packageMatch == null) {
                        // use the default package name, since mixing with package-less code will break
                        packageMatch = new String[] { "", packageName };
                        // add the package name to the source before writing it
                        javaCode = "package " + packageName + ";" + javaCode;
                    }
                    File packageFolder = new File(srcFolder, packageMatch[1].replace('.', File.separatorChar));
                    packageFolder.mkdirs();
                    Util.saveFile(javaCode, new File(packageFolder, filename));
                }
            } catch (IOException e) {
                e.printStackTrace();
                String msg = "Problem moving " + filename + " to the build folder";
                throw new SketchException(msg);
            }
        } else if (sc.isExtension("pde")) {
            // The compiler and runner will need this to have a proper offset
            sc.addPreprocOffset(result.headerOffset);
        }
    }
    foundMain = preprocessor.hasMethod("main");
    return result.className;
}
Also used : SketchCode(processing.app.SketchCode) StringList(processing.data.StringList) SketchException(processing.app.SketchException) BuildException(org.apache.tools.ant.BuildException) PreprocessorResult(processing.mode.java.preproc.PreprocessorResult) SketchException(processing.app.SketchException) Library(processing.app.Library) ZipFile(java.util.zip.ZipFile) SurfaceInfo(processing.mode.java.preproc.SurfaceInfo)

Aggregations

ZipFile (java.util.zip.ZipFile)1 BuildException (org.apache.tools.ant.BuildException)1 Library (processing.app.Library)1 SketchCode (processing.app.SketchCode)1 SketchException (processing.app.SketchException)1 StringList (processing.data.StringList)1 PreprocessorResult (processing.mode.java.preproc.PreprocessorResult)1 SurfaceInfo (processing.mode.java.preproc.SurfaceInfo)1