JDK-6902720 : javac pretty printer does not handle enums correctly
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 7
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2009-11-18
  • Updated: 2019-09-04
  • Resolved: 2012-01-13
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7
7 b78Fixed
Related Reports
Relates :  
Description
javac's Pretty class does not correctly handle enum constant declarations when the declaration involves use of a non-default constructor. The args to be passed to the constructor get hidden inside a comment, meaning that the actual code printed is incorrect and cannot be compiled.
Here's a test program:
--------------------------------------------------------
import java.io.*;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;


import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.util.JavacTask;
import com.sun.tools.javac.api.JavacTool;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.Pretty;
public class Test {

    public static void main(String[] args) throws Exception {
        new Test().run(args);
    }

    void run(String... args) throws IOException {
        PrintWriter out = new PrintWriter(System.out);
        try {
            JavacTool tool = JavacTool.create();
            StandardJavaFileManager fm = tool.getStandardFileManager(null, null,
 null);

            Iterable<? extends JavaFileObject> files = fm.getJavaFileObjects(arg
s);

            JavacTask t = tool.getTask(null, fm, null, null, null, files);
            Iterable<? extends CompilationUnitTree> trees = t.parse();
            for (CompilationUnitTree tree: trees) {
                new Pretty(out, true).printExpr((JCTree) tree);
            }
        } finally {
            out.flush();
        }
    }
}
---------------------------------------------------------

Run it on this source:
-------------------------------
enum E {
    E1(1), E2(2), E3(3);
    E(int i) { }
}
-------------------------------

to get:
-------------------------------
enum E {
    /*public static final*/ E1 /* = new E(1) */,
    /*public static final*/ E2 /* = new E(2) */,
    /*public static final*/ E3 /* = new E(3) */;
    
    E(int i) {
    }
}
-------------------------------

Compiling that output gives the following, because of the incorrect code generated:
-------------------------------
error: cannot find symbol
symbol  : constructor E()
location: class E
1 error
-------------------------------

Comments
EVALUATION Fixed in this changeset: http://hg.openjdk.java.net/jdk7/tl/langtools/rev/b1bb8164a9bd
08-12-2009

EVALUATION The problem comes because the enum is desugared right in the parser, meaning that there is no direct tree to be printed; instead the enum decl is parsed directly into an "equivelent" desugared tree. This desugared tree is what is printed as a comment by Pretty. The fix is to have Pretty analyze the tree and reverse it back to its original source form. This is made relatively easy by the presence of the ENUM bit on the decl's modifiers. In addition, for maximum compatibility, the existing boolean "sourceOutput" is used to control whether the reverse analysis is done, or if the output remains as now. Thus, "sourceOutput" must be set true for the new code to take effect.
19-11-2009