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;
}
Aggregations