diff --git a/app/src/processing/mode/java/AutoFormat.java b/app/src/processing/mode/java/AutoFormat.java
index 935e2a903..91d8a7cec 100644
--- a/app/src/processing/mode/java/AutoFormat.java
+++ b/app/src/processing/mode/java/AutoFormat.java
@@ -38,56 +38,62 @@ import processing.core.PApplet;
*
* After some further digging, this code in fact appears to be a modified
* version of Jason Pell's GPLed "Java Beautifier" class found
- * here.
- * Which is itself based on code from Van Di-Han Ho from
- * here.
+ * here,
+ * which is itself based on code from Van Di-Han Ho from
+ * here.
* [Ben Fry, August 2009]
*/
public class AutoFormat implements Formatter {
private char[] chars;
private final StringBuilder buf = new StringBuilder();
-
private final StringBuilder result = new StringBuilder();
private int indentValue;
private boolean EOF;
- private boolean a_flg, e_flg, if_flg, s_flag, q_flg;
- private boolean s_if_flg[];
+ private boolean a_flg, if_flg, s_flag, elseFlag;
+
+ /** Number of ? entered without exiting at : of a?b:c structures. */
+ private int conditionalLevel;
+
private int pos;
-// private int lineNumber;
- private int s_level[];
private int c_level;
- private int sp_flg[][];
- private int s_ind[][];
- private int s_if_lev[];
- private int if_lev, level;
- private int ind[];
- private int paren;
- private int p_flg[];
+ private int[][] sp_flg;
+ private int[][] s_ind;
+ private int if_lev;
+
+ /** Number of curly brackets entered and not exited. */
+ private int level;
+
+ /** Number of parentheses entered and not exited. */
+ private int parenLevel;
+
+ private int[] ind;
+ private int[] p_flg;
private char l_char;
- private int ct;
- private int s_tabs[][];
+ private int[][] s_tabs;
private boolean jdoc_flag;
private char cc;
private int tabs;
private char c;
+ private char lastNonWhitespace = 0;
private final Stack castFlags = new Stack();
- private void comment() {
- final boolean save_s_flg = s_flag;
+ private void handleMultiLineComment() {
+ final boolean saved_s_flag = s_flag;
- buf.append(c = next()); // extra char
+ char ch;
+ buf.append(ch = nextChar()); // extra char
while (true) {
- buf.append(c = next());
- while ((c != '/')) {
- if (c == '\n') {
-// lineNumber++;
+ buf.append(ch = nextChar());
+ while (ch != '/') {
+ if (ch == '\n') {
+// lineNumber++;
writeIndentedComment();
s_flag = true;
}
- buf.append(c = next());
+ buf.append(ch = nextChar());
}
if (buf.length() >= 2 && buf.charAt(buf.length() - 2) == '*') {
jdoc_flag = false;
@@ -96,50 +102,65 @@ public class AutoFormat implements Formatter {
}
writeIndentedComment();
- s_flag = save_s_flg;
+ s_flag = saved_s_flag;
jdoc_flag = false;
return;
}
-
- private char get_string() {
- char ch;
- while (true) {
- buf.append(ch = next());
- if (ch == '\\') {
- buf.append(next());
- continue;
- }
- if (ch == '\'' || ch == '"') {
- buf.append(cc = next());
- while (!EOF && cc != ch) {
- if (cc == '\\') {
- buf.append(next());
- }
- buf.append(cc = next());
- }
- continue;
- }
- if (ch == '\n') {
- writeIndentedLine();
- a_flg = true;
- continue;
- }
- return ch;
+
+ private void handleSingleLineComment() {
+ char ch = nextChar();
+ while (ch != '\n') {
+ buf.append(ch);
+ ch = nextChar();
}
+// lineNumber++;
+ writeIndentedLine();
+ s_flag = true;
}
+
+// /**
+// * Transfers buf to result until a character is reached that
+// * is neither \, \n, or in a string. \n is not written, but
+// * writeIndentedLine is called on finding it.
+// * @return The first character not listed above.
+// */
+// private char get_string() {
+// char ch1, ch2;
+// while (true) {
+// buf.append(ch1 = nextChar());
+// if (ch1 == '\\') {
+// buf.append(nextChar());
+// } else if (ch1 == '\'' || ch1 == '\"') {
+// buf.append(ch2 = nextChar());
+// while (!EOF && ch2 != ch1) {
+// if (ch2 == '\\') {
+// // Next char is escaped, ignore.
+// buf.append(nextChar());
+// }
+// buf.append(ch2 = nextChar());
+// }
+// } else if (ch1 == '\n') {
+// writeIndentedLine();
+// a_flg = true;
+// } else {
+// return ch1;
+// }
+// }
+// }
+
private void writeIndentedLine() {
if (buf.length() == 0) {
if (s_flag) {
- s_flag = a_flg = e_flg = false;
+ s_flag = a_flg = elseFlag = false;
}
return;
}
if (s_flag) {
- final boolean shouldIndent = (tabs > 0) && (buf.charAt(0) != '{')
- && a_flg;
+ final boolean shouldIndent =
+ (tabs > 0) && (buf.charAt(0) != '{') && a_flg;
if (shouldIndent) {
tabs++;
}
@@ -150,23 +171,22 @@ public class AutoFormat implements Formatter {
}
a_flg = false;
}
- if (e_flg) {
+ if (elseFlag) {
if (lastNonSpaceChar() == '}') {
trimRight(result);
- result.append(" ");
+ result.append(' ');
}
- e_flg = false;
+ elseFlag = false;
}
result.append(buf);
buf.setLength(0);
}
-
+
private char lastNonSpaceChar() {
- for (int i=result.length()-1; i>=0; i--) {
+ for (int i = result.length() - 1; i >= 0; i--) {
char c_i = result.charAt(i);
- if (c_i == ' ' || c_i == '\n') continue;
- else return c_i;
+ if (c_i != ' ' && c_i != '\n') return c_i;
}
return 0;
}
@@ -187,7 +207,7 @@ public class AutoFormat implements Formatter {
jdoc_flag = true;
}
if (buf.charAt(i) == '/' && buf.charAt(i + 1) == '*') {
- if (saved_s_flag && prev() != ';') {
+ if (saved_s_flag && getLastNonWhitespace() != ';') {
result.append(buf.substring(i));
} else {
result.append(buf);
@@ -204,18 +224,6 @@ public class AutoFormat implements Formatter {
}
- private void handleSingleLineComment() {
- c = next();
- while (c != '\n') {
- buf.append(c);
- c = next();
- }
-// lineNumber++;
- writeIndentedLine();
- s_flag = true;
- }
-
-
private void printIndentation() {
if (tabs < 0) {
tabs = 0;
@@ -225,7 +233,7 @@ public class AutoFormat implements Formatter {
}
final int spaces = tabs * indentValue;
for (int k = 0; k < spaces; k++) {
- result.append(" ");
+ result.append(' ');
}
}
@@ -238,10 +246,7 @@ public class AutoFormat implements Formatter {
}
- private char lastNonWhitespace = 0;
-
-
- private int prev() {
+ private int getLastNonWhitespace() {
return lastNonWhitespace;
}
@@ -256,33 +261,32 @@ public class AutoFormat implements Formatter {
if (pos == chars.length - 1) {
EOF = true;
} else {
- pos--; // reset for next()
+ pos--; // reset for nextChar()
}
}
- private char next() {
+ private char nextChar() {
if (EOF) {
- return 0;
+ return '\0';
}
pos++;
- final char c;
+ char retVal;
if (pos < chars.length) {
- c = chars[pos];
- if (!Character.isWhitespace(c))
- lastNonWhitespace = c;
+ retVal = chars[pos];
+ if (!Character.isWhitespace(retVal))
+ lastNonWhitespace = retVal;
} else {
- c = 0;
+ retVal = '\0';
}
- if (pos == chars.length - 1) {
+ if (pos == chars.length-1) {
EOF = true;
}
- return c;
+ return retVal;
}
- /* else processing */
- private void gotelse() {
+ private void gotElse() {
tabs = s_tabs[c_level][if_lev];
p_flg[level] = sp_flg[c_level][if_lev];
ind[level] = s_ind[c_level][if_lev];
@@ -290,23 +294,22 @@ public class AutoFormat implements Formatter {
}
- /* read to new_line */
- private boolean getnl() {
+ private boolean readUntilNewLine() {
final int savedTabs = tabs;
char c = peek();
while (!EOF && (c == '\t' || c == ' ')) {
- buf.append(next());
+ buf.append(nextChar());
c = peek();
}
if (c == '/') {
- buf.append(next());
+ buf.append(nextChar());
c = peek();
if (c == '*') {
- buf.append(next());
- comment();
+ buf.append(nextChar());
+ handleMultiLineComment();
} else if (c == '/') {
- buf.append(next());
+ buf.append(nextChar());
handleSingleLineComment();
return true;
}
@@ -315,7 +318,7 @@ public class AutoFormat implements Formatter {
c = peek();
if (c == '\n') {
// eat it
- next();
+ nextChar();
// lineNumber++;
tabs = savedTabs;
return true;
@@ -344,24 +347,25 @@ public class AutoFormat implements Formatter {
public String format(final String source) {
final String normalizedText = source.replaceAll("\r", "");
- final String cleanText = normalizedText
- + (normalizedText.endsWith("\n") ? "" : "\n");
+ final String cleanText =
+ normalizedText + (normalizedText.endsWith("\n") ? "" : "\n");
result.setLength(0);
indentValue = Preferences.getInteger("editor.tabs.size");
-// lineNumber = 0;
- q_flg = e_flg = a_flg = if_flg = false;
+// lineNumber = 0;
+ boolean forFlag = a_flg = if_flg = false;
s_flag = true;
- c_level = if_lev = level = paren = 0;
+ int forParenthLevel = 0;
+ conditionalLevel = parenLevel = c_level = if_lev = level = 0;
tabs = 0;
jdoc_flag = false;
- s_level = new int[10];
+ int[] s_level = new int[10];
sp_flg = new int[20][10];
s_ind = new int[20][10];
- s_if_lev = new int[10];
- s_if_flg = new boolean[10];
+ int[] s_if_lev = new int[10];
+ boolean[] s_if_flg = new boolean[10];
ind = new int[10];
p_flg = new int[10];
s_tabs = new int[20][10];
@@ -369,10 +373,10 @@ public class AutoFormat implements Formatter {
chars = cleanText.toCharArray();
// lineNumber = 1;
- EOF = false; // set in next() when EOF
+ EOF = false; // set in nextChar() when EOF
while (!EOF) {
- c = next();
+ c = nextChar();
switch (c) {
default:
buf.append(c);
@@ -388,12 +392,13 @@ public class AutoFormat implements Formatter {
case ' ':
case '\t':
- e_flg = lookup("else");
- if (e_flg) {
- gotelse();
+ elseFlag = lookup("else");
+ if (elseFlag) {
+ gotElse();
if ((!s_flag) || buf.length() > 0) {
buf.append(c);
}
+
writeIndentedLine();
s_flag = false;
break;
@@ -408,9 +413,9 @@ public class AutoFormat implements Formatter {
if (EOF) {
break;
}
- e_flg = lookup("else");
- if (e_flg) {
- gotelse();
+ elseFlag = lookup("else");
+ if (elseFlag) {
+ gotElse();
}
if (lookup_com("//")) {
final char lastChar = buf.charAt(buf.length() - 1);
@@ -422,19 +427,18 @@ public class AutoFormat implements Formatter {
writeIndentedLine();
result.append("\n");
s_flag = true;
- if (e_flg) {
+ if (elseFlag) {
p_flg[level]++;
tabs++;
- } else if (prev() == l_char) {
+ } else if (getLastNonWhitespace() == l_char) {
a_flg = true;
}
break;
case '{':
- e_flg = lookup("else");
- if (e_flg) {
- gotelse();
- }
+ elseFlag = lookup("else");
+ if (elseFlag) gotElse();
+
if (s_if_lev.length == c_level) {
s_if_lev = PApplet.expand(s_if_lev);
s_if_flg = PApplet.expand(s_if_flg);
@@ -454,9 +458,9 @@ public class AutoFormat implements Formatter {
buf.append(" ");
buf.append(c);
writeIndentedLine();
- getnl();
+ readUntilNewLine();
writeIndentedLine();
- //fprintf(outfil,"\n");
+
result.append("\n");
tabs++;
s_flag = true;
@@ -489,11 +493,12 @@ public class AutoFormat implements Formatter {
printIndentation();
result.append(c);
if (peek() == ';') {
- result.append(next());
+ result.append(nextChar());
}
- getnl();
+
+ readUntilNewLine();
writeIndentedLine();
- result.append("\n");
+ result.append('\n');
s_flag = true;
if (c_level < s_level[level]) {
if (level > 0) {
@@ -511,21 +516,21 @@ public class AutoFormat implements Formatter {
case '"':
case '\'':
buf.append(c);
- cc = next();
+ cc = nextChar();
while (!EOF && cc != c) {
buf.append(cc);
if (cc == '\\') {
- buf.append(cc = next());
+ buf.append(cc = nextChar());
}
if (cc == '\n') {
// lineNumber++;
writeIndentedLine();
s_flag = true;
}
- cc = next();
+ cc = nextChar();
}
buf.append(cc);
- if (getnl()) {
+ if (readUntilNewLine()) {
l_char = cc;
// push a newline into the stream
chars[pos--] = '\n';
@@ -533,13 +538,21 @@ public class AutoFormat implements Formatter {
break;
case ';':
+ if (forFlag) {
+ // This is like a comma.
+ trimRight(buf);
+ buf.append("; ");
+ // Not non-whitespace: allow \n.
+ advanceToNonSpace();
+ break;
+ }
buf.append(c);
writeIndentedLine();
if (p_flg[level] > 0 && ind[level] == 0) {
tabs -= p_flg[level];
p_flg[level] = 0;
}
- getnl();
+ readUntilNewLine();
writeIndentedLine();
result.append("\n");
s_flag = true;
@@ -555,26 +568,39 @@ public class AutoFormat implements Formatter {
case '\\':
buf.append(c);
- buf.append(next());
+ buf.append(nextChar());
break;
case '?':
- q_flg = true;
+ conditionalLevel++;
buf.append(c);
break;
case ':':
- buf.append(c);
+ // Java 8 :: operator.
if (peek() == ':') {
writeIndentedLine();
- result.append(next());
+ result.append(c).append(nextChar());
break;
}
- if (q_flg) {
- q_flg = false;
+ // End a?b:c structures.
+ else if (conditionalLevel>0) {
+ conditionalLevel--;
+ buf.append(c);
break;
}
+
+ else if (forFlag) {
+ trimRight(buf);
+ buf.append(" : ");
+ // Not to non-whitespace: allow \n.
+ advanceToNonSpace();
+ break;
+ }
+
+ buf.append(c);
+
if (!lookup("default") && !lookup("case")) {
s_flag = false;
writeIndentedLine();
@@ -584,26 +610,27 @@ public class AutoFormat implements Formatter {
tabs++;
}
if (peek() == ';') {
- result.append(next());
+ result.append(nextChar());
}
- getnl();
+ readUntilNewLine();
writeIndentedLine();
- result.append("\n");
+ result.append('\n');
s_flag = true;
break;
case '/':
- final char la = peek();
- if (la == '/') {
- buf.append(c).append(next());
+ final char next = peek();
+ if (next == '/') {
+ // call nextChar to move on.
+ buf.append(c).append(nextChar());
handleSingleLineComment();
result.append("\n");
- } else if (la == '*') {
+ } else if (next == '*') {
if (buf.length() > 0) {
writeIndentedLine();
}
- buf.append(c).append(next());
- comment();
+ buf.append(c).append(nextChar());
+ handleMultiLineComment();
} else {
buf.append(c);
}
@@ -613,15 +640,23 @@ public class AutoFormat implements Formatter {
final boolean isCast = castFlags.isEmpty() ? false : castFlags.pop();
- paren--;
- if (paren < 0) {
- paren = 0;
+ parenLevel--;
+
+ // If we're further back than the start of a for loop, we've
+ // left it.
+ if (forFlag && forParenthLevel > parenLevel) {
+ forFlag = false;
}
+
+ if (parenLevel < 0) {
+ parenLevel = 0;
+ }
+
buf.append(c);
writeIndentedLine();
- if (getnl()) {
+ if (readUntilNewLine()) {
chars[pos--] = '\n';
- if (paren != 0) {
+ if (parenLevel != 0) {
a_flg = true;
} else if (tabs > 0 && !isCast) {
p_flg[level]++;
@@ -644,42 +679,16 @@ public class AutoFormat implements Formatter {
}
buf.append(c);
- paren++;
+ parenLevel++;
+ // isFor says "is it the start of a for?". If it is, we set forFlag and
+ // forParenthLevel. If it is not parenth_lvl was incremented above and
+ // that's it.
if (isFor) {
- // TODO(feinberg): handle new-style for loops
- c = get_string();
- while (c != ';' && c != ':') {
- c = get_string();
+ if (!forFlag) {
+ forParenthLevel = parenLevel;
+ forFlag = true;
}
- ct = 0;
- int for_done = 0;
- while (for_done == 0) {
- c = get_string();
- while (c != ')') {
- if (c == '(') {
- ct++;
- }
- c = get_string();
- }
- if (ct != 0) {
- ct--;
- } else {
- for_done = 1;
- }
- } // endwhile for_done
- paren--;
- if (paren < 0) {
- paren = 0;
- }
- writeIndentedLine();
- if (getnl()) {
- chars[pos--] = '\n';
- p_flg[level]++;
- tabs++;
- ind[level] = 0;
- }
- break;
} else if (isIf) {
writeIndentedLine();
s_tabs[c_level][if_lev] = tabs;