8024415: Bug in javac Pretty: Wrong precedence in JCConditional trees

Tue, 08 Oct 2013 15:33:28 +0200

author
alundblad
date
Tue, 08 Oct 2013 15:33:28 +0200
changeset 2097
ea000904db62
parent 2091
4dd7ffbf01fb
child 2098
0be3f1820e8b

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 +}

mercurial