Mon, 21 Jan 2013 20:19:53 +0000
8005166: Add support for static interface methods
Summary: Support public static interface methods
Reviewed-by: jjg
mcimadamore@1513 | 1 | /* |
mcimadamore@1513 | 2 | * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. |
mcimadamore@1513 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
mcimadamore@1513 | 4 | * |
mcimadamore@1513 | 5 | * This code is free software; you can redistribute it and/or modify it |
mcimadamore@1513 | 6 | * under the terms of the GNU General Public License version 2 only, as |
mcimadamore@1513 | 7 | * published by the Free Software Foundation. |
mcimadamore@1513 | 8 | * |
mcimadamore@1513 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
mcimadamore@1513 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
mcimadamore@1513 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
mcimadamore@1513 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
mcimadamore@1513 | 13 | * accompanied this code). |
mcimadamore@1513 | 14 | * |
mcimadamore@1513 | 15 | * You should have received a copy of the GNU General Public License version |
mcimadamore@1513 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
mcimadamore@1513 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
mcimadamore@1513 | 18 | * |
mcimadamore@1513 | 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
mcimadamore@1513 | 20 | * or visit www.oracle.com if you need additional information or have any |
mcimadamore@1513 | 21 | * questions. |
mcimadamore@1513 | 22 | */ |
mcimadamore@1513 | 23 | |
mcimadamore@1513 | 24 | /* |
mcimadamore@1513 | 25 | * @test |
mcimadamore@1513 | 26 | * @bug 8005166 |
mcimadamore@1513 | 27 | * @summary Add support for static interface methods |
mcimadamore@1513 | 28 | * Smoke test for static interface method hiding |
mcimadamore@1513 | 29 | */ |
mcimadamore@1513 | 30 | |
mcimadamore@1513 | 31 | import com.sun.source.util.JavacTask; |
mcimadamore@1513 | 32 | import java.net.URI; |
mcimadamore@1513 | 33 | import java.util.Arrays; |
mcimadamore@1513 | 34 | import javax.tools.Diagnostic; |
mcimadamore@1513 | 35 | import javax.tools.JavaCompiler; |
mcimadamore@1513 | 36 | import javax.tools.JavaFileObject; |
mcimadamore@1513 | 37 | import javax.tools.SimpleJavaFileObject; |
mcimadamore@1513 | 38 | import javax.tools.StandardJavaFileManager; |
mcimadamore@1513 | 39 | import javax.tools.ToolProvider; |
mcimadamore@1513 | 40 | |
mcimadamore@1513 | 41 | |
mcimadamore@1513 | 42 | public class InterfaceMethodHidingTest { |
mcimadamore@1513 | 43 | |
mcimadamore@1513 | 44 | static int checkCount = 0; |
mcimadamore@1513 | 45 | |
mcimadamore@1513 | 46 | enum SignatureKind { |
mcimadamore@1513 | 47 | VOID_INTEGER("void m(Integer s)", "return;"), |
mcimadamore@1513 | 48 | STRING_INTEGER("String m(Integer s)", "return null;"), |
mcimadamore@1513 | 49 | VOID_STRING("void m(String s)", "return;"), |
mcimadamore@1513 | 50 | STRING_STRING("String m(String s)", "return null;"); |
mcimadamore@1513 | 51 | |
mcimadamore@1513 | 52 | String sigStr; |
mcimadamore@1513 | 53 | String retStr; |
mcimadamore@1513 | 54 | |
mcimadamore@1513 | 55 | SignatureKind(String sigStr, String retStr) { |
mcimadamore@1513 | 56 | this.sigStr = sigStr; |
mcimadamore@1513 | 57 | this.retStr = retStr; |
mcimadamore@1513 | 58 | } |
mcimadamore@1513 | 59 | |
mcimadamore@1513 | 60 | boolean overrideEquivalentWith(SignatureKind s2) { |
mcimadamore@1513 | 61 | switch (this) { |
mcimadamore@1513 | 62 | case VOID_INTEGER: |
mcimadamore@1513 | 63 | case STRING_INTEGER: |
mcimadamore@1513 | 64 | return s2 == VOID_INTEGER || s2 == STRING_INTEGER; |
mcimadamore@1513 | 65 | case VOID_STRING: |
mcimadamore@1513 | 66 | case STRING_STRING: |
mcimadamore@1513 | 67 | return s2 == VOID_STRING || s2 == STRING_STRING; |
mcimadamore@1513 | 68 | default: |
mcimadamore@1513 | 69 | throw new AssertionError("bad signature kind"); |
mcimadamore@1513 | 70 | } |
mcimadamore@1513 | 71 | } |
mcimadamore@1513 | 72 | } |
mcimadamore@1513 | 73 | |
mcimadamore@1513 | 74 | enum MethodKind { |
mcimadamore@1513 | 75 | VIRTUAL("", "#M #S;"), |
mcimadamore@1513 | 76 | STATIC("static", "#M #S { #BE; #R }"), |
mcimadamore@1513 | 77 | DEFAULT("default", "#M #S { #BE; #R }"); |
mcimadamore@1513 | 78 | |
mcimadamore@1513 | 79 | String modStr; |
mcimadamore@1513 | 80 | String methTemplate; |
mcimadamore@1513 | 81 | |
mcimadamore@1513 | 82 | MethodKind(String modStr, String methTemplate) { |
mcimadamore@1513 | 83 | this.modStr = modStr; |
mcimadamore@1513 | 84 | this.methTemplate = methTemplate; |
mcimadamore@1513 | 85 | } |
mcimadamore@1513 | 86 | |
mcimadamore@1513 | 87 | boolean inherithed() { |
mcimadamore@1513 | 88 | return this != STATIC; |
mcimadamore@1513 | 89 | } |
mcimadamore@1513 | 90 | |
mcimadamore@1513 | 91 | static boolean overrides(MethodKind mk1, SignatureKind sk1, MethodKind mk2, SignatureKind sk2) { |
mcimadamore@1513 | 92 | return sk1 == sk2 && |
mcimadamore@1513 | 93 | mk2.inherithed() && |
mcimadamore@1513 | 94 | mk1 != STATIC; |
mcimadamore@1513 | 95 | } |
mcimadamore@1513 | 96 | |
mcimadamore@1513 | 97 | String getBody(BodyExpr be, SignatureKind sk) { |
mcimadamore@1513 | 98 | return methTemplate.replaceAll("#BE", be.bodyExprStr) |
mcimadamore@1513 | 99 | .replaceAll("#R", sk.retStr) |
mcimadamore@1513 | 100 | .replaceAll("#M", modStr) |
mcimadamore@1513 | 101 | .replaceAll("#S", sk.sigStr); |
mcimadamore@1513 | 102 | } |
mcimadamore@1513 | 103 | } |
mcimadamore@1513 | 104 | |
mcimadamore@1513 | 105 | enum BodyExpr { |
mcimadamore@1513 | 106 | NONE(""), |
mcimadamore@1513 | 107 | THIS("Object o = this"); |
mcimadamore@1513 | 108 | |
mcimadamore@1513 | 109 | String bodyExprStr; |
mcimadamore@1513 | 110 | |
mcimadamore@1513 | 111 | BodyExpr(String bodyExprStr) { |
mcimadamore@1513 | 112 | this.bodyExprStr = bodyExprStr; |
mcimadamore@1513 | 113 | } |
mcimadamore@1513 | 114 | |
mcimadamore@1513 | 115 | boolean allowed(MethodKind mk) { |
mcimadamore@1513 | 116 | return this == NONE || |
mcimadamore@1513 | 117 | mk != MethodKind.STATIC; |
mcimadamore@1513 | 118 | } |
mcimadamore@1513 | 119 | } |
mcimadamore@1513 | 120 | |
mcimadamore@1513 | 121 | public static void main(String... args) throws Exception { |
mcimadamore@1513 | 122 | |
mcimadamore@1513 | 123 | //create default shared JavaCompiler - reused across multiple compilations |
mcimadamore@1513 | 124 | JavaCompiler comp = ToolProvider.getSystemJavaCompiler(); |
mcimadamore@1513 | 125 | StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null); |
mcimadamore@1513 | 126 | |
mcimadamore@1513 | 127 | for (MethodKind mk1 : MethodKind.values()) { |
mcimadamore@1513 | 128 | for (SignatureKind sk1 : SignatureKind.values()) { |
mcimadamore@1513 | 129 | for (BodyExpr be1 : BodyExpr.values()) { |
mcimadamore@1513 | 130 | for (MethodKind mk2 : MethodKind.values()) { |
mcimadamore@1513 | 131 | for (SignatureKind sk2 : SignatureKind.values()) { |
mcimadamore@1513 | 132 | for (BodyExpr be2 : BodyExpr.values()) { |
mcimadamore@1513 | 133 | for (MethodKind mk3 : MethodKind.values()) { |
mcimadamore@1513 | 134 | for (SignatureKind sk3 : SignatureKind.values()) { |
mcimadamore@1513 | 135 | for (BodyExpr be3 : BodyExpr.values()) { |
mcimadamore@1513 | 136 | new InterfaceMethodHidingTest(mk1, mk2, mk3, sk1, sk2, sk3, be1, be2, be3).run(comp, fm); |
mcimadamore@1513 | 137 | } |
mcimadamore@1513 | 138 | } |
mcimadamore@1513 | 139 | } |
mcimadamore@1513 | 140 | } |
mcimadamore@1513 | 141 | } |
mcimadamore@1513 | 142 | } |
mcimadamore@1513 | 143 | } |
mcimadamore@1513 | 144 | } |
mcimadamore@1513 | 145 | } |
mcimadamore@1513 | 146 | System.out.println("Total check executed: " + checkCount); |
mcimadamore@1513 | 147 | } |
mcimadamore@1513 | 148 | |
mcimadamore@1513 | 149 | MethodKind mk1, mk2, mk3; |
mcimadamore@1513 | 150 | SignatureKind sk1, sk2, sk3; |
mcimadamore@1513 | 151 | BodyExpr be1, be2, be3; |
mcimadamore@1513 | 152 | JavaSource source; |
mcimadamore@1513 | 153 | DiagnosticChecker diagChecker; |
mcimadamore@1513 | 154 | |
mcimadamore@1513 | 155 | InterfaceMethodHidingTest(MethodKind mk1, MethodKind mk2, MethodKind mk3, |
mcimadamore@1513 | 156 | SignatureKind sk1, SignatureKind sk2, SignatureKind sk3, BodyExpr be1, BodyExpr be2, BodyExpr be3) { |
mcimadamore@1513 | 157 | this.mk1 = mk1; |
mcimadamore@1513 | 158 | this.mk2 = mk2; |
mcimadamore@1513 | 159 | this.mk3 = mk3; |
mcimadamore@1513 | 160 | this.sk1 = sk1; |
mcimadamore@1513 | 161 | this.sk2 = sk2; |
mcimadamore@1513 | 162 | this.sk3 = sk3; |
mcimadamore@1513 | 163 | this.be1 = be1; |
mcimadamore@1513 | 164 | this.be2 = be2; |
mcimadamore@1513 | 165 | this.be3 = be3; |
mcimadamore@1513 | 166 | this.source = new JavaSource(); |
mcimadamore@1513 | 167 | this.diagChecker = new DiagnosticChecker(); |
mcimadamore@1513 | 168 | } |
mcimadamore@1513 | 169 | |
mcimadamore@1513 | 170 | class JavaSource extends SimpleJavaFileObject { |
mcimadamore@1513 | 171 | |
mcimadamore@1513 | 172 | String template = "interface Sup {\n" + |
mcimadamore@1513 | 173 | " default void sup() { }\n" + |
mcimadamore@1513 | 174 | "}\n" + |
mcimadamore@1513 | 175 | "interface A extends Sup {\n" + |
mcimadamore@1513 | 176 | " #M1\n" + |
mcimadamore@1513 | 177 | "}\n" + |
mcimadamore@1513 | 178 | "interface B extends A, Sup {\n" + |
mcimadamore@1513 | 179 | " #M2\n" + |
mcimadamore@1513 | 180 | "}\n" + |
mcimadamore@1513 | 181 | "interface C extends B, Sup {\n" + |
mcimadamore@1513 | 182 | " #M3\n" + |
mcimadamore@1513 | 183 | "}\n"; |
mcimadamore@1513 | 184 | |
mcimadamore@1513 | 185 | String source; |
mcimadamore@1513 | 186 | |
mcimadamore@1513 | 187 | public JavaSource() { |
mcimadamore@1513 | 188 | super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); |
mcimadamore@1513 | 189 | source = template.replaceAll("#M1", mk1.getBody(be1, sk1)) |
mcimadamore@1513 | 190 | .replaceAll("#M2", mk2.getBody(be2, sk2)) |
mcimadamore@1513 | 191 | .replaceAll("#M3", mk3.getBody(be3, sk3)); |
mcimadamore@1513 | 192 | } |
mcimadamore@1513 | 193 | |
mcimadamore@1513 | 194 | @Override |
mcimadamore@1513 | 195 | public CharSequence getCharContent(boolean ignoreEncodingErrors) { |
mcimadamore@1513 | 196 | return source; |
mcimadamore@1513 | 197 | } |
mcimadamore@1513 | 198 | } |
mcimadamore@1513 | 199 | |
mcimadamore@1513 | 200 | void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception { |
mcimadamore@1513 | 201 | JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker, |
mcimadamore@1513 | 202 | Arrays.asList("-XDallowStaticInterfaceMethods"), null, Arrays.asList(source)); |
mcimadamore@1513 | 203 | try { |
mcimadamore@1513 | 204 | ct.analyze(); |
mcimadamore@1513 | 205 | } catch (Throwable ex) { |
mcimadamore@1513 | 206 | throw new AssertionError("Error thrown when analyzing the following source:\n" + source.getCharContent(true)); |
mcimadamore@1513 | 207 | } |
mcimadamore@1513 | 208 | check(); |
mcimadamore@1513 | 209 | } |
mcimadamore@1513 | 210 | |
mcimadamore@1513 | 211 | void check() { |
mcimadamore@1513 | 212 | boolean errorExpected = |
mcimadamore@1513 | 213 | !be1.allowed(mk1) || !be2.allowed(mk2) || !be3.allowed(mk3); |
mcimadamore@1513 | 214 | |
mcimadamore@1513 | 215 | if (mk1.inherithed()) { |
mcimadamore@1513 | 216 | errorExpected |= |
mcimadamore@1513 | 217 | sk2.overrideEquivalentWith(sk1) && !MethodKind.overrides(mk2, sk2, mk1, sk1) || |
mcimadamore@1513 | 218 | sk3.overrideEquivalentWith(sk1) && !MethodKind.overrides(mk3, sk3, mk1, sk1); |
mcimadamore@1513 | 219 | } |
mcimadamore@1513 | 220 | |
mcimadamore@1513 | 221 | if (mk2.inherithed()) { |
mcimadamore@1513 | 222 | errorExpected |= |
mcimadamore@1513 | 223 | sk3.overrideEquivalentWith(sk2) && !MethodKind.overrides(mk3, sk3, mk2, sk2); |
mcimadamore@1513 | 224 | } |
mcimadamore@1513 | 225 | |
mcimadamore@1513 | 226 | checkCount++; |
mcimadamore@1513 | 227 | if (diagChecker.errorFound != errorExpected) { |
mcimadamore@1513 | 228 | throw new AssertionError("Problem when compiling source:\n" + source.getCharContent(true) + |
mcimadamore@1513 | 229 | "\nfound error: " + diagChecker.errorFound); |
mcimadamore@1513 | 230 | } |
mcimadamore@1513 | 231 | } |
mcimadamore@1513 | 232 | |
mcimadamore@1513 | 233 | static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> { |
mcimadamore@1513 | 234 | |
mcimadamore@1513 | 235 | boolean errorFound; |
mcimadamore@1513 | 236 | |
mcimadamore@1513 | 237 | public void report(Diagnostic<? extends JavaFileObject> diagnostic) { |
mcimadamore@1513 | 238 | if (diagnostic.getKind() == Diagnostic.Kind.ERROR) { |
mcimadamore@1513 | 239 | errorFound = true; |
mcimadamore@1513 | 240 | } |
mcimadamore@1513 | 241 | } |
mcimadamore@1513 | 242 | } |
mcimadamore@1513 | 243 | } |