T6996914a.java revision 2933:49d207bf704d
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 6996914 7020044 8062373
27 * @summary  Diamond inference: problem when accessing protected constructor
28 * @modules jdk.compiler
29 * @run main T6996914a
30 */
31
32import com.sun.source.util.JavacTask;
33import java.net.URI;
34import java.util.Arrays;
35import javax.tools.Diagnostic;
36import javax.tools.DiagnosticListener;
37import javax.tools.JavaCompiler;
38import javax.tools.JavaFileObject;
39import javax.tools.SimpleJavaFileObject;
40import javax.tools.ToolProvider;
41
42public class T6996914a {
43
44    enum PackageKind {
45        DEFAULT("", ""),
46        A("package a;", "import a.*;");
47
48        String pkgDecl;
49        String importDecl;
50
51        PackageKind(String pkgDecl, String importDecl) {
52            this.pkgDecl = pkgDecl;
53            this.importDecl = importDecl;
54        }
55    }
56
57    enum DiamondKind {
58        STANDARD("new Foo<>();"),
59        ANON("new Foo<>() {};");
60
61        String expr;
62
63        DiamondKind(String expr) {
64            this.expr = expr;
65        }
66    }
67
68    enum ConstructorKind {
69        PACKAGE(""),
70        PROTECTED("protected"),
71        PRIVATE("private"),
72        PUBLIC("public");
73
74        String mod;
75
76        ConstructorKind(String mod) {
77            this.mod = mod;
78        }
79    }
80
81    static class FooClass extends SimpleJavaFileObject {
82
83        final static String sourceStub =
84                        "#P\n" +
85                        "public class Foo<X> {\n" +
86                        "  #M Foo() {}\n" +
87                        "}\n";
88
89        String source;
90
91        public FooClass(PackageKind pk, ConstructorKind ck) {
92            super(URI.create("myfo:/" + (pk != PackageKind.DEFAULT ? "a/Foo.java" : "Foo.java")),
93                    JavaFileObject.Kind.SOURCE);
94            source = sourceStub.replace("#P", pk.pkgDecl).replace("#M", ck.mod);
95        }
96
97        @Override
98        public CharSequence getCharContent(boolean ignoreEncodingErrors) {
99            return source;
100        }
101    }
102
103    static class ClientClass extends SimpleJavaFileObject {
104
105        final static String sourceStub =
106                        "#I\n" +
107                        "class Test {\n" +
108                        "  Foo<String> fs = #D\n" +
109                        "}\n";
110
111        String source;
112
113        public ClientClass(PackageKind pk, DiamondKind dk) {
114            super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
115            source = sourceStub.replace("#I", pk.importDecl).replace("#D", dk.expr);
116        }
117
118        @Override
119        public CharSequence getCharContent(boolean ignoreEncodingErrors) {
120            return source;
121        }
122    }
123
124    public static void main(String... args) throws Exception {
125        for (PackageKind pk : PackageKind.values()) {
126            for (ConstructorKind ck : ConstructorKind.values()) {
127                for (DiamondKind dk : DiamondKind.values()) {
128                    compileAndCheck(pk, ck, dk);
129                }
130            }
131        }
132    }
133
134    static void compileAndCheck(PackageKind pk, ConstructorKind ck, DiamondKind dk) throws Exception {
135        FooClass foo = new FooClass(pk, ck);
136        ClientClass client = new ClientClass(pk, dk);
137        final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
138        ErrorListener el = new ErrorListener();
139        JavacTask ct = (JavacTask)tool.getTask(null, null, el,
140                null, null, Arrays.asList(foo, client));
141        ct.analyze();
142        if (el.errors > 0 == check(pk, ck, dk)) {
143            String msg = el.errors > 0 ?
144                "Error compiling files" :
145                "No error when compiling files";
146            throw new AssertionError(msg + ": \n" + foo.source + "\n" + client.source);
147        }
148    }
149
150    static boolean check(PackageKind pk, ConstructorKind ck, DiamondKind dk) {
151        switch (pk) {
152            case A: return ck == ConstructorKind.PUBLIC ||
153                    (ck  == ConstructorKind.PROTECTED && dk == DiamondKind.ANON);
154            case DEFAULT: return ck != ConstructorKind.PRIVATE;
155            default: throw new AssertionError("Unknown package kind");
156        }
157    }
158
159    /**
160     * DiagnosticListener to count any errors that occur
161     */
162    private static class ErrorListener implements DiagnosticListener<JavaFileObject> {
163
164        public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
165            switch (diagnostic.getKind()) {
166                case ERROR:
167                    errors++;
168            }
169        }
170        int errors;
171    }
172}
173