1/*
2 * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/*
25 * @test
26 * @bug 6921495
27 * @summary spurious semicolons in class def cause empty NOPOS blocks
28 * @modules jdk.compiler
29 */
30
31import java.io.*;
32import java.net.*;
33import java.util.*;
34import javax.tools.*;
35import com.sun.source.util.*;
36
37public class ExtraSemiTest {
38
39    static class JavaSource extends SimpleJavaFileObject {
40
41        final static String source =
42                        "class C {\n" +
43                        "    int x;;\n" +
44                        "    class X { int i;; };\n" +
45                        "}";
46
47        JavaSource() {
48            super(URI.create("myfo:/C.java"), JavaFileObject.Kind.SOURCE);
49        }
50
51        @Override
52        public CharSequence getCharContent(boolean ignoreEncodingErrors) {
53            return source;
54        }
55    }
56
57    public static void main(String... args) throws IOException {
58        new ExtraSemiTest().run();
59    }
60
61    void run() throws IOException {
62        File destDir = new File("classes"); destDir.mkdir();
63        final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
64        JavaSource source = new JavaSource();
65        JavacTask ct = (JavacTask)tool.getTask(null, null, null,
66                Arrays.asList("-d", destDir.getPath(), "-XD-printsource"),
67                null,
68                Arrays.asList(source));
69        Boolean ok = ct.call();
70        if (!ok) throw new AssertionError("compilation failed");
71
72        String text = readFile(new File(destDir, "C.java"));
73        System.out.println(text);
74
75        // compress/canonicalize all whitespace
76        String canon = text.replaceAll("\\s+", " ");
77        System.out.println("canon: " + canon);
78
79        // There are no empty blocks in the original text.
80        // C will be given a default constructor "C() { super(); }" which
81        // does not have any empty blocks.
82        // The bug is that spurious semicolons in the class defn are parsed
83        // into redundant empty blocks in the tree, so verify there are
84        // no empty blocks in the -printsource output
85
86        if (canon.contains("{ }"))
87            throw new AssertionError("unexpected empty block found");
88    }
89
90    String readFile(File f) throws IOException {
91        int len = (int) f.length();
92        byte[] data = new byte[len];
93        DataInputStream in = new DataInputStream(new FileInputStream(f));
94        try {
95            in.readFully(data);
96            return new String(data);
97        } finally {
98            in.close();
99        }
100    }
101}
102