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