Tue, 08 Oct 2013 15:33:28 +0200
8024415: Bug in javac Pretty: Wrong precedence in JCConditional trees
Summary: Fixed precedence and associativity issues with pretty printing of JCConditional expressions.
Reviewed-by: jfranck
Contributed-by: Andreas Lundblad <andreas.lundblad@oracle.com>, Matthew Dempsky <mdempsky@google.com>
src/share/classes/com/sun/tools/javac/tree/Pretty.java | file | annotate | diff | comparison | revisions | |
test/tools/javac/tree/T8024415.java | file | annotate | diff | comparison | revisions |
1.1 --- a/src/share/classes/com/sun/tools/javac/tree/Pretty.java Mon Oct 07 16:51:56 2013 -0700 1.2 +++ b/src/share/classes/com/sun/tools/javac/tree/Pretty.java Tue Oct 08 15:33:28 2013 +0200 1.3 @@ -782,9 +782,9 @@ 1.4 public void visitConditional(JCConditional tree) { 1.5 try { 1.6 open(prec, TreeInfo.condPrec); 1.7 - printExpr(tree.cond, TreeInfo.condPrec); 1.8 + printExpr(tree.cond, TreeInfo.condPrec + 1); 1.9 print(" ? "); 1.10 - printExpr(tree.truepart, TreeInfo.condPrec); 1.11 + printExpr(tree.truepart); 1.12 print(" : "); 1.13 printExpr(tree.falsepart, TreeInfo.condPrec); 1.14 close(prec, TreeInfo.condPrec);
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/test/tools/javac/tree/T8024415.java Tue Oct 08 15:33:28 2013 +0200 2.3 @@ -0,0 +1,113 @@ 2.4 +/* 2.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 2.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 2.7 + * 2.8 + * This code is free software; you can redistribute it and/or modify it 2.9 + * under the terms of the GNU General Public License version 2 only, as 2.10 + * published by the Free Software Foundation. 2.11 + * 2.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 2.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 2.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 2.15 + * version 2 for more details (a copy is included in the LICENSE file that 2.16 + * accompanied this code). 2.17 + * 2.18 + * You should have received a copy of the GNU General Public License version 2.19 + * 2 along with this work; if not, write to the Free Software Foundation, 2.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2.21 + * 2.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2.23 + * or visit www.oracle.com if you need additional information or have any 2.24 + * questions. 2.25 + */ 2.26 + 2.27 +/* 2.28 + * @test 2.29 + * @bug 8024415 2.30 + * @summary Pretty printing of JCConditional does not follow the precedence and 2.31 + * associativity rules of JCConditional 2.32 + * @run testng T8024415 2.33 + */ 2.34 + 2.35 + 2.36 +import static org.testng.Assert.assertEquals; 2.37 + 2.38 +import java.io.IOException; 2.39 +import java.io.StringWriter; 2.40 + 2.41 +import org.testng.annotations.Test; 2.42 + 2.43 +import com.sun.tools.javac.file.JavacFileManager; 2.44 +import com.sun.tools.javac.tree.JCTree; 2.45 +import com.sun.tools.javac.tree.JCTree.JCExpression; 2.46 +import com.sun.tools.javac.tree.Pretty; 2.47 +import com.sun.tools.javac.tree.TreeMaker; 2.48 +import com.sun.tools.javac.util.Context; 2.49 +import com.sun.tools.javac.util.Names; 2.50 + 2.51 + 2.52 +/* 2.53 + * Test verifies that the precedence rules of conditional expressions 2.54 + * (JCConditional) are correct. 2.55 + */ 2.56 +@Test 2.57 +public class T8024415 { 2.58 + 2.59 + TreeMaker maker; 2.60 + JCExpression x; 2.61 + 2.62 + 2.63 + public T8024415() { 2.64 + Context ctx = new Context(); 2.65 + JavacFileManager.preRegister(ctx); 2.66 + maker = TreeMaker.instance(ctx); 2.67 + Names names = Names.instance(ctx); 2.68 + x = maker.Ident(names.fromString("x")); 2.69 + } 2.70 + 2.71 + 2.72 + // JLS 15.25: The conditional operator is syntactically right-associative 2.73 + // (it groups right-to-left). Thus, a?b:c?d:e?f:g means the same as 2.74 + // a?b:(c?d:(e?f:g)). 2.75 + public void testAssociativity() throws IOException { 2.76 + 2.77 + JCTree left = maker.Conditional(maker.Conditional(x, x, x), x, x); 2.78 + JCTree right = maker.Conditional(x, x, maker.Conditional(x, x, x)); 2.79 + 2.80 + String prettyLeft = prettyPrint(left); 2.81 + String prettyRight = prettyPrint(right); 2.82 + 2.83 + assertEquals(prettyLeft.replaceAll("\\s", ""), "(x?x:x)?x:x"); 2.84 + assertEquals(prettyRight.replaceAll("\\s", ""), "x?x:x?x:x"); 2.85 + 2.86 + } 2.87 + 2.88 + 2.89 + // The true-part of of a conditional expression is surrounded by ? and : 2.90 + // and can thus always be parsed unambiguously without surrounding 2.91 + // parentheses. 2.92 + public void testPrecedence() throws IOException { 2.93 + 2.94 + JCTree left = maker.Conditional(maker.Assign(x, x), x, x); 2.95 + JCTree middle = maker.Conditional(x, maker.Assign(x, x), x); 2.96 + JCTree right = maker.Conditional(x, x, maker.Assign(x, x)); 2.97 + 2.98 + String prettyLeft = prettyPrint(left); 2.99 + String prettyMiddle = prettyPrint(middle); 2.100 + String prettyRight = prettyPrint(right); 2.101 + 2.102 + assertEquals(prettyLeft.replaceAll("\\s", ""), "(x=x)?x:x"); 2.103 + assertEquals(prettyMiddle.replaceAll("\\s", ""), "x?x=x:x"); 2.104 + assertEquals(prettyRight.replaceAll("\\s", ""), "x?x:(x=x)"); 2.105 + 2.106 + } 2.107 + 2.108 + 2.109 + // Helper method 2.110 + private static String prettyPrint(JCTree tree) throws IOException { 2.111 + StringWriter sw = new StringWriter(); 2.112 + new Pretty(sw, true).printExpr(tree); 2.113 + return sw.toString(); 2.114 + } 2.115 + 2.116 +}