Skip to content

Commit

Permalink
Harden JavaSourcePrettyPrinter to cope with (hopefully) all possible …
Browse files Browse the repository at this point in the history
…for-loop body types
  • Loading branch information
ntoster committed Mar 23, 2023
1 parent 30ae1f1 commit 9a21641
Show file tree
Hide file tree
Showing 3 changed files with 446 additions and 62 deletions.
32 changes: 26 additions & 6 deletions JavaSourcePrettyPrinter.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.tree.*;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.*;
import java.io.*;
import java.util.*;
import java.io.IOException;
import java.io.Writer;

public class JavaSourcePrettyPrinter extends com.sun.tools.javac.tree.Pretty {
private boolean inEnum = false;
Expand Down Expand Up @@ -144,8 +144,28 @@ public void visitForLoop(JCForLoop forLoop) {
print(statement.expr);
}
print(") ");
if (forLoop.body instanceof JCBlock body) super.visitBlock(body);
if (forLoop.body instanceof JCSkip noBody) super.visitSkip(noBody);
if (forLoop.body instanceof JCAssert body) super.visitAssert(body);
else if (forLoop.body instanceof JCBlock body) super.visitBlock(body);
else if (forLoop.body instanceof JCBreak body) super.visitBreak(body);
else if (forLoop.body instanceof JCCase body) super.visitCase(body);
else if (forLoop.body instanceof JCClassDecl body) super.visitClassDef(body);
else if (forLoop.body instanceof JCContinue body) super.visitContinue(body);
else if (forLoop.body instanceof JCDoWhileLoop body) super.visitDoLoop(body);
else if (forLoop.body instanceof JCEnhancedForLoop body) super.visitForeachLoop(body);
else if (forLoop.body instanceof JCExpressionStatement body) super.visitExec(body);
else if (forLoop.body instanceof JCForLoop body) super.visitForLoop(body);
else if (forLoop.body instanceof JCIf body) super.visitIf(body);
else if (forLoop.body instanceof JCLabeledStatement body) super.visitLabelled(body);
else if (forLoop.body instanceof JCReturn body) super.visitReturn(body);
else if (forLoop.body instanceof JCSkip body) super.visitSkip(body);
else if (forLoop.body instanceof JCSwitch body) super.visitSwitch(body);
else if (forLoop.body instanceof JCSynchronized body) super.visitSynchronized(body);
else if (forLoop.body instanceof JCThrow body) super.visitThrow(body);
else if (forLoop.body instanceof JCTry body) super.visitTry(body);
else if (forLoop.body instanceof JCVariableDecl body) super.visitVarDef(body);
else if (forLoop.body instanceof JCWhileLoop body) super.visitWhileLoop(body);
else if (forLoop.body instanceof JCYield body) super.visitYield(body);
else print(forLoop.body); // FIXME: missing anything else here? try best effort if so...
} catch (IOException e) {
throw new Error("something failed while pretty printing: " + e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,58 +33,240 @@ public static int toTest() {
return sum;
}

// ================================================================================
// ensure that the PrettyPrinter still outputs valid Java code:
public static int toTestRegression() {
// ensure that the PrettyPrinter still outputs valid Java code:
// --- all simple ---
for (int a = 0; a < DIGITS.size(); a++) {
var v = DIGITS.get(a);
toTestRegression_for_loop_A_1_simple_for();
toTestRegression_for_loop_A_2_simple_for_each();
toTestRegression_for_loop_B_1_no_init();
toTestRegression_for_loop_B_2_no_condition();
toTestRegression_for_loop_B_3_no_increment();
toTestRegression_for_loop_B_4_empty_head();
toTestRegression_for_loop_B_5_multiple_init_and_def_in_condition_and_multiple_post_op();
toTestRegression_for_loop_C_1_empty_body();
toTestRegression_for_loop_D_1_nested_for_loop_body();
toTestRegression_for_loop_D_2_nested_for_each_loop_body();
toTestRegression_for_loop_D_3_nested_while_loop_body();
toTestRegression_for_loop_D_4_nested_do_while_loop_body();
toTestRegression_for_loop_D_5_labelled_nested_for_loop();
toTestRegression_for_loop_E_01_single_expression_statement_body();
toTestRegression_for_loop_E_02_method_call_body();
toTestRegression_for_loop_E_03_switch_body();
toTestRegression_for_loop_E_04_array_access_body();
toTestRegression_for_loop_E_05_assert_body();
toTestRegression_for_loop_E_06_assign_body();
toTestRegression_for_loop_E_07_try_body();
try {
toTestRegression_for_loop_E_08_throw_body();
} catch (IllegalArgumentException ignored) {
}
toTestRegression_for_loop_E_09_break();
toTestRegression_for_loop_E_10_continue();
toTestRegression_for_loop_E_11_return();
toTestRegression_for_loop_E_12_field_access();
toTestRegression_for_loop_E_13_synchronized();
return toTest();
}

private static void toTestRegression_for_loop_A_1_simple_for() {
for (int a = 0; a < DIGITS.size(); a++) { // intentionally not for-each!
var v = DIGITS.get(0);
if (v < 0 || 10 < v) {
throw new IllegalArgumentException();
}
}
// --- no init ---
int b = 0;
for (; b < DIGITS.size(); b++) {
var v = DIGITS.get(b);
}

private static void toTestRegression_for_loop_A_2_simple_for_each() {
for (int v : DIGITS) { // intentionally for-each!
if (v < 0 || 10 < v) {
throw new IllegalArgumentException();
}
}
// --- no condition ---
for (int c = 0; ; c++) {
if (c >= DIGITS.size()) break;
var v = DIGITS.get(c);
}

private static void toTestRegression_for_loop_B_1_no_init() {
int a = 0;
for (; a < DIGITS.size(); a++) { // intentionally no init!
var v = DIGITS.get(a);
if (v < 0 || 10 < v) {
throw new IllegalArgumentException();
}
}
}

private static void toTestRegression_for_loop_B_2_no_condition() {
for (int a = 0; ; a++) { // intentionally no condition!
if (a >= DIGITS.size()) break;
var v = DIGITS.get(a);
if (v < 0 || 10 < v) {
throw new IllegalArgumentException();
}
}
// --- no increment ---
for (int d = 0; d < DIGITS.size(); ) {
var v = DIGITS.get(d);
}

private static void toTestRegression_for_loop_B_3_no_increment() {
for (int a = 0; a < DIGITS.size(); ) { // intentionally no post-inc/dec!
var v = DIGITS.get(a);
if (v < 0 || 10 < v) {
throw new IllegalArgumentException();
}
d++;
a++;
}
// --- nothing in the head ---
int e = 0;
for (; ; ) {
if (e >= DIGITS.size()) break;
var v = DIGITS.get(e);
}

private static void toTestRegression_for_loop_B_4_empty_head() {
int a = 0;
for (; ; ) { // intentionally no init, no condition, no post-inc/dec!
if (a >= DIGITS.size()) break;
var v = DIGITS.get(a);
if (v < 0 || 10 < v) {
throw new IllegalArgumentException();
}
e++;
a++;
}
// --- no body ---
for (int a = 0; a < DIGITS.size(); a++) ; // yes: there should be no loop body!
// --- several init and increment, definition in condition ---
for (int f = 0, g = -1, h = 1, v; f < DIGITS.size() && g-- < 0; f++, h--) {
v = DIGITS.get(f);
}

private static void toTestRegression_for_loop_B_5_multiple_init_and_def_in_condition_and_multiple_post_op() {
for (int a = 0, b = -1, c = 1, v; a < DIGITS.size() && b-- < 0; a++, c--) { // intentionally quirky
v = DIGITS.get(a);
if (v < 0 || 10 < v) {
throw new IllegalArgumentException();
}
}
return toTest();
}

private static void toTestRegression_for_loop_C_1_empty_body() {
var x = 42;
for (int a = 0; a < DIGITS.size(); a++) ; // intentionally no loop body!
System.out.println(x);
}

private static void toTestRegression_for_loop_D_1_nested_for_loop_body() {
for (int a = 0; a < DIGITS.size(); a++)
for (int b = 0; b < DIGITS.size(); b++)
System.out.println(a + "/" + b);
System.out.println(DIGITS);
}

private static void toTestRegression_for_loop_D_2_nested_for_each_loop_body() {
for (int a = 0; a < DIGITS.size(); a++)
for (int b : DIGITS)
System.out.println(a + "/" + b);
System.out.println(DIGITS);
}

private static void toTestRegression_for_loop_D_3_nested_while_loop_body() {
int a = 10;
for (int b = 0; b < DIGITS.size(); b++)
while (a-- > 0) System.out.println(b + "/" + a);
System.out.println(DIGITS);
}

private static void toTestRegression_for_loop_D_4_nested_do_while_loop_body() {
int a = 10;
for (int b = 0; b < DIGITS.size(); b++)
do System.out.println(b + "/" + a); while (a-- > 0);
System.out.println(DIGITS);
}

private static void toTestRegression_for_loop_D_5_labelled_nested_for_loop() {
for (int a = 0; a < DIGITS.size(); a++)
middle:for (int b = 0; b < DIGITS.size(); b++)
for (int c = 0; c < DIGITS.size(); c++)
if (b == 5) break middle;
System.out.println(DIGITS);
}

private static void toTestRegression_for_loop_E_01_single_expression_statement_body() {
for (int a = 0; a < DIGITS.size(); a++)
System.out.println(a);
System.out.println(DIGITS);
}

private static void toTestRegression_for_loop_E_02_method_call_body() {
for (int a = 0; a < DIGITS.size(); a++)
toTest();
System.out.println(DIGITS);
}

private static void toTestRegression_for_loop_E_03_switch_body() {
for (int a = 0; a < DIGITS.size(); a++)
switch (a) {
case 0 -> System.out.println(0);
case 1 -> System.out.println(1);
}
System.out.println(DIGITS);
}

private static void toTestRegression_for_loop_E_04_array_access_body() {
int[] x = {0, 1, 2, 3, 4, 5};
for (int a = 0; a < DIGITS.size(); a++)
x[0]++;
System.out.println(x[0]);
}

private static void toTestRegression_for_loop_E_05_assert_body() {
for (int a = 0; a < DIGITS.size(); a++)
assert DIGITS.get(0) >= 0;
System.out.println(DIGITS);
}

private static void toTestRegression_for_loop_E_06_assign_body() {
int y = 0;
for (int a = 0; a < DIGITS.size(); a++)
y = a;
System.out.println(y);
}

private static void toTestRegression_for_loop_E_07_try_body() {
int y = 0;
for (int a = 0; a < DIGITS.size(); a++)
try {
y = Integer.parseInt("0");
} catch (NumberFormatException ignored) {
}
System.out.println(y);
}

private static void toTestRegression_for_loop_E_08_throw_body() {
for (int a = 0; a < DIGITS.size(); )
throw new IllegalArgumentException(); // intentionally thrown
System.out.println(DIGITS);
}

private static void toTestRegression_for_loop_E_09_break() {
for (int a = 0; a < DIGITS.size(); )
break; // intentionally break
System.out.println(DIGITS);
}

private static void toTestRegression_for_loop_E_10_continue() {
for (int a = 0; a < DIGITS.size(); a++)
continue; // intentionally continue
System.out.println(DIGITS);
}

private static void toTestRegression_for_loop_E_11_return() {
for (int a = 0; a < DIGITS.size(); a++)
return; // intentionally return
System.out.println(DIGITS);
}

int aField = 0;

private static void toTestRegression_for_loop_E_12_field_access() {
ToTest tt = new ToTest();
for (int a = 0; a < DIGITS.size(); a++)
tt.aField++;
System.out.println(DIGITS);
}

private static void toTestRegression_for_loop_E_13_synchronized() {
for (int a = 0; a < DIGITS.size(); a++)
synchronized (Integer.class) {
System.out.println("String");
}
System.out.println(DIGITS);
}
}
Loading

0 comments on commit 9a21641

Please sign in to comment.