From 714181181058216322b8a3affdf2e4df44f78142 Mon Sep 17 00:00:00 2001 From: Ben Fry Date: Thu, 4 Jun 2015 15:22:25 -0500 Subject: [PATCH] change up how size() is parsed and handled --- java/src/processing/mode/java/JavaBuild.java | 8 +- .../mode/java/preproc/PdePreprocessor.java | 229 ++++++++++++------ .../mode/java/preproc/SizeInfo.java | 98 ++++++++ 3 files changed, 264 insertions(+), 71 deletions(-) create mode 100644 java/src/processing/mode/java/preproc/SizeInfo.java diff --git a/java/src/processing/mode/java/JavaBuild.java b/java/src/processing/mode/java/JavaBuild.java index 87027321d..d37a3db92 100644 --- a/java/src/processing/mode/java/JavaBuild.java +++ b/java/src/processing/mode/java/JavaBuild.java @@ -248,19 +248,21 @@ public class JavaBuild { // 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 = + //String[] sizeParts = + SizeInfo sizeInfo = preprocessor.initSketchSize(sketch.getMainProgram(), sizeWarning); //System.out.format("size() is '%s'%n", info[0]); // Remove the size() statement (will be added back by writeFooter()) - if (sizeParts != null) { - String sizeStatement = sizeParts[0]; + if (sizeInfo != null) { + String sizeStatement = sizeInfo.getStatement(); if (sizeStatement != null) { int index = bigCode.indexOf(sizeStatement); bigCode.delete(index, index + sizeStatement.length()); } } + PreprocessorResult result; try { File outputFolder = (packageName == null) ? diff --git a/java/src/processing/mode/java/preproc/PdePreprocessor.java b/java/src/processing/mode/java/preproc/PdePreprocessor.java index 882ea0142..7a9095cba 100644 --- a/java/src/processing/mode/java/preproc/PdePreprocessor.java +++ b/java/src/processing/mode/java/preproc/PdePreprocessor.java @@ -153,13 +153,86 @@ public class PdePreprocessor { // private boolean foundMain; private String advClassName = ""; protected Mode mode; - HashMap foundMethods; + Set foundMethods; + +// protected String sizeStatement; +// protected String sketchWidth; +// protected String sketchHeight; +// protected String sketchRenderer; +// protected String sketchOutputPath; + + /* + static class SizeInfo { + String statement; + String width; + String height; + String renderer; + String path; + String display; + +// SizeInfo(String statement, String width, String height, +// String renderer, String outputPath, String display) { +// this.statement = statement; +// } + + boolean hasOldSyntax() { + if (width.equals("screenWidth") || + width.equals("screenHeight") || + height.equals("screenHeight") || + height.equals("screenWidth")) { + final String message = + "The screenWidth and screenHeight variables are named\n" + + "displayWidth and displayHeight in Processing 3.\n" + + "Or you can use the fullScreen() method instead of size()."; + Base.showWarning("Time for a quick update", message, null); + return true; + } + if (width.equals("screen.width") || + width.equals("screen.height") || + height.equals("screen.height") || + height.equals("screen.width")) { + final String message = + "The screen.width and screen.height variables are named\n" + + "displayWidth and displayHeight in Processing 3.\n" + + "Or you can use the fullScreen() method instead of size()."; + Base.showWarning("Time for a quick update", message, null); + return true; + } + return false; + } + + boolean hasBadSize() { + if (!width.equals("displayWidth") && + !width.equals("displayHeight") && + PApplet.parseInt(width, -1) == -1) { + return true; + } + if (!height.equals("displayWidth") && + !height.equals("displayHeight") && + PApplet.parseInt(height, -1) == -1) { + return true; + } + return false; + } + + + void checkEmpty() { + if (renderer != null) { + if (renderer.length() == 0) { // if empty, set null + renderer = null; + } + } + if (path != null) { + if (path.length() == 0) { + path = null; + } + } + } + } + */ + + SizeInfo sizeInfo; - protected String sizeStatement; - protected String sketchWidth; - protected String sketchHeight; - protected String sketchRenderer; - protected String sketchOutputPath; /** * Regular expression for parsing the size() method. This should match @@ -172,6 +245,13 @@ public class PdePreprocessor { // "(?:^|\\s|;)size\\s*\\(\\s*([^\\s,]+)\\s*,\\s*([^\\s,\\)]+)\\s*,?\\s*([^\\)]*)\\s*\\)\\s*\\;"; static private final String SIZE_CONTENTS_REGEX = "(?:^|\\s|;)size\\s*\\(([^\\)]+)\\)\\s*\\;"; + static private final String FULL_SCREEN_CONTENTS_REGEX = + "(?:^|\\s|;)fullScreen\\s*\\(([^\\)]+)\\)\\s*\\;"; + /** Test whether there's a void somewhere (the program has functions). */ + static private final String VOID_REGEX = + "(?:^|\\s|;)void\\s"; + static private final String VOID_SETUP_REGEX = + "(?:^|\\s|;)void\\ssetup\\s*\\("; static private final Pattern PUBLIC_CLASS = @@ -201,17 +281,18 @@ public class PdePreprocessor { } - public String[] initSketchSize(String code, boolean sizeWarning) throws SketchException { - String[] info = parseSketchSize(code, sizeWarning); - //PApplet.printArray(info); - if (info != null) { - sizeStatement = info[0]; - sketchWidth = info[1]; - sketchHeight = info[2]; - sketchRenderer = info[3]; - sketchOutputPath = info[4]; - } - return info; + public SizeInfo initSketchSize(String code, boolean sizeWarning) throws SketchException { +// String[] info = parseSketchSize(code, sizeWarning); +// if (info != null) { +// sizeStatement = info[0]; +// sketchWidth = info[1]; +// sketchHeight = info[2]; +// sketchRenderer = info[3]; +// sketchOutputPath = info[4]; +// } +// return info; + sizeInfo = parseSketchSize(code, sizeWarning); + return sizeInfo; } @@ -259,7 +340,7 @@ public class PdePreprocessor { * @param fussy true if it should show an error message if bad size() * @return null if there was an error, otherwise an array (might contain some/all nulls) */ - static public String[] parseSketchSize(String code, boolean fussy) { + static public SizeInfo parseSketchSize(String code, boolean fussy) { // This matches against any uses of the size() function, whether numbers // or variables or whatever. This way, no warning is shown if size() isn't // actually used in the applet, which is the case especially for anyone @@ -269,47 +350,71 @@ public class PdePreprocessor { // String[] matches = PApplet.match(scrubbed, SIZE_REGEX); // String[] matches = PApplet.match(scrubComments(code), SIZE_REGEX); + /* + 1. no size() or fullScreen() method at all + will use the non-overridden settings() method in PApplet + 2. size() or fullScreen() found inside setup() (static mode sketch or otherwise) + make sure that it uses numbers (or displayWidth/Height), copy into settings + 3. size() or fullScreen() already in settings() + don't mess with the sketch, don't insert any defaults + + really only need to deal with situation #2.. nothing to be done for 1 and 3 + */ + // if static mode sketch, all we need is regex + // easy proxy for static in this case is whether [^\s]void\s is present + + String searchArea = scrubComments(code); + String[] setupMatch = PApplet.match(searchArea, VOID_SETUP_REGEX); + if (setupMatch != null) { + String found = setupMatch[0]; + int start = searchArea.indexOf(found) + found.length(); + int openBrace = searchArea.indexOf("{", start); + char[] c = searchArea.toCharArray(); + int depth = 0; + int closeBrace = -1; + StringBuilder sb = new StringBuilder(); + for (int i = openBrace; i < c.length; i++) { + if (c[i] == '{') { + depth++; + } else if (c[i] == '}') { + depth--; + if (depth == 0) { + closeBrace = ++i; + break; + } + } else { + sb.append(c[i]); + } + } + if (closeBrace == -1) { +// throw new SketchException("Found a { that's missing a matching }"); + return null; + } + searchArea = sb.toString(); + } + // Get everything inside the parens for the size() method - String[] contents = PApplet.match(scrubComments(code), SIZE_CONTENTS_REGEX); + String[] contents = PApplet.match(searchArea, SIZE_CONTENTS_REGEX); if (contents != null) { //String[] matches = split on commas, but not commas inside quotes StringList args = breakCommas(contents[1]); - String width = args.get(0).trim(); - String height = args.get(1).trim(); - String renderer = (args.size() >= 3) ? args.get(2) : null; - String path = (args.size() >= 4) ? args.get(3) : null; - - boolean badSize = false; + SizeInfo info = new SizeInfo(); + info.statement = contents[0]; + info.width = args.get(0).trim(); + info.height = args.get(1).trim(); + info.renderer = (args.size() >= 3) ? args.get(2).trim() : null; + info.path = (args.size() >= 4) ? args.get(3).trim() : null; // Trying to remember why we wanted to allow people to use displayWidth // as the height or displayHeight as the width, but maybe it's for // making a square sketch window? Not going to - if (width.equals("screenWidth") || - width.equals("screenHeight") || - height.equals("screenHeight") || - height.equals("screenWidth")) { - final String message = - "The screenWidth and screenHeight variables\n" + - "are named displayWidth and displayHeight\n" + - "in this release of Processing."; - Base.showWarning("Time for a quick update", message, null); + if (info.hasOldSyntax()) { return null; } - if (!width.equals("displayWidth") && - !width.equals("displayHeight") && - PApplet.parseInt(width, -1) == -1) { - badSize = true; - } - if (!height.equals("displayWidth") && - !height.equals("displayHeight") && - PApplet.parseInt(height, -1) == -1) { - badSize = true; - } - - if (badSize && fussy) { + if (info.hasBadSize() && fussy) { // found a reference to size, but it didn't seem to contain numbers final String message = "The size of this applet could not automatically\n" + @@ -321,25 +426,13 @@ public class PdePreprocessor { return null; } - // Remove additional space 'round the renderer - if (renderer != null) { - renderer = renderer.trim(); - if (renderer.length() == 0) { // if empty, set null - renderer = null; - } - } - - // Same for the file name - if (path != null) { - path = path.trim(); - if (path.length() == 0) { - path = null; - } - } - return new String[] { contents[0], width, height, renderer, path }; + info.checkEmpty(); + return info; + //return new String[] { contents[0], width, height, renderer, path }; } // not an error, just no size() specified - return new String[] { null, null, null, null, null }; + //return new String[] { null, null, null, null, null }; + return new SizeInfo(); } @@ -405,12 +498,12 @@ public class PdePreprocessor { public void addMethod(String methodName) { - foundMethods.put(methodName, new Object()); + foundMethods.add(methodName); } public boolean hasMethod(String methodName) { - return foundMethods.containsKey(methodName); + return foundMethods.contains(methodName); } @@ -571,7 +664,7 @@ public class PdePreprocessor { // need to reset whether or not this has a main() // foundMain = false; - foundMethods = new HashMap(); + foundMethods = new HashSet(); // http://processing.org/bugs/bugzilla/5.html if (!program.endsWith("\n")) { @@ -941,8 +1034,8 @@ public class PdePreprocessor { if ((mode == Mode.STATIC) || (mode == Mode.ACTIVE)) { // doesn't remove the oriiginal size() method, but calling size() // again in setup() is harmless. - if (!hasMethod("settings") && sizeStatement != null) { - out.println(indent + "public void settings() { " + sizeStatement + " }"); + if (!hasMethod("settings") && sizeInfo.statement != null) { + out.println(indent + "public void settings() { " + sizeInfo.statement + " }"); // out.println(indent + "public void settings() {"); // out.println(indent + indent + sizeStatement); // out.println(indent + "}"); diff --git a/java/src/processing/mode/java/preproc/SizeInfo.java b/java/src/processing/mode/java/preproc/SizeInfo.java new file mode 100644 index 000000000..c884da9a1 --- /dev/null +++ b/java/src/processing/mode/java/preproc/SizeInfo.java @@ -0,0 +1,98 @@ +/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + SizeInfo - parsed elements of a size() or fullScreen() call + Part of the Processing project - http://processing.org + + Copyright (c) 2015 Ben Fry and Casey Reas + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + 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 processing.mode.java.preproc; + +import processing.app.Base; +import processing.core.PApplet; + + +public class SizeInfo { + String statement; + String width; + String height; + String renderer; + String path; + String display; + + + boolean hasOldSyntax() { + if (width.equals("screenWidth") || + width.equals("screenHeight") || + height.equals("screenHeight") || + height.equals("screenWidth")) { + final String message = + "The screenWidth and screenHeight variables are named\n" + + "displayWidth and displayHeight in Processing 3.\n" + + "Or you can use the fullScreen() method instead of size()."; + Base.showWarning("Time for a quick update", message, null); + return true; + } + if (width.equals("screen.width") || + width.equals("screen.height") || + height.equals("screen.height") || + height.equals("screen.width")) { + final String message = + "The screen.width and screen.height variables are named\n" + + "displayWidth and displayHeight in Processing 3.\n" + + "Or you can use the fullScreen() method instead of size()."; + Base.showWarning("Time for a quick update", message, null); + return true; + } + return false; + } + + + boolean hasBadSize() { + if (!width.equals("displayWidth") && + !width.equals("displayHeight") && + PApplet.parseInt(width, -1) == -1) { + return true; + } + if (!height.equals("displayWidth") && + !height.equals("displayHeight") && + PApplet.parseInt(height, -1) == -1) { + return true; + } + return false; + } + + + void checkEmpty() { + if (renderer != null) { + if (renderer.length() == 0) { // if empty, set null + renderer = null; + } + } + if (path != null) { + if (path.length() == 0) { + path = null; + } + } + } + + + public String getStatement() { + return statement; + } +}