TestDuplicateImport.java revision 3170:dc017a37aac5
1/* 2 * Copyright (c) 2011, 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 7101822 27 * @summary static import fails to resolve interfaces on nested enums via import statements 28 * @modules jdk.compiler 29 */ 30 31import com.sun.source.util.JavacTask; 32import java.net.URI; 33import java.util.Arrays; 34import javax.tools.Diagnostic; 35import javax.tools.JavaCompiler; 36import javax.tools.JavaFileObject; 37import javax.tools.SimpleJavaFileObject; 38import javax.tools.StandardJavaFileManager; 39import javax.tools.ToolProvider; 40 41 42public class TestDuplicateImport { 43 44 static int checkCount = 0; 45 46 enum ImportKind { 47 NORMAL("import a.#Q.#N;"), 48 STATIC("import static a.#Q.#N;"); 49 50 String importStr; 51 52 ImportKind(String importStr) { 53 this.importStr = importStr; 54 } 55 56 String getImportStatement(QualifierKind qk, NameKind nk) { 57 return importStr.replaceAll("#Q", qk.qualifierStr) 58 .replaceAll("#N", nk.nameStr); 59 } 60 61 boolean isStatic() { 62 return this == STATIC; 63 } 64 } 65 66 enum QualifierKind { 67 A("A"), 68 B("B"), 69 C("C"); 70 71 String qualifierStr; 72 73 QualifierKind(String qualifierStr) { 74 this.qualifierStr = qualifierStr; 75 } 76 77 public boolean compatible(QualifierKind ik) { 78 return this == ik || (this != A && ik != A); 79 } 80 } 81 82 enum NameKind { 83 D("D"), 84 E("E"), 85 M("m"), 86 F("f"), 87 STAR("*"), 88 NON_EXISTENT("NonExistent"); 89 90 String nameStr; 91 92 NameKind(String nameStr) { 93 this.nameStr = nameStr; 94 } 95 96 boolean exists() { 97 return this != NON_EXISTENT; 98 } 99 100 boolean isMember() { 101 return this == M || this == F; 102 } 103 104 boolean isType() { 105 return this == D || this == E; 106 } 107 } 108 109 public static void main(String... args) throws Exception { 110 111 //create default shared JavaCompiler - reused across multiple compilations 112 JavaCompiler comp = ToolProvider.getSystemJavaCompiler(); 113 StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null); 114 115 for (ImportKind ik1 : ImportKind.values()) { 116 for (ImportKind ik2 : ImportKind.values()) { 117 for (QualifierKind qk1 : QualifierKind.values()) { 118 for (QualifierKind qk2 : QualifierKind.values()) { 119 for (NameKind nk1 : NameKind.values()) { 120 for (NameKind nk2 : NameKind.values()) { 121 new TestDuplicateImport(ik1, ik2, qk1, qk2, nk1, nk2).run(comp, fm); 122 } 123 } 124 } 125 } 126 } 127 } 128 System.out.println("Total check executed: " + checkCount); 129 } 130 131 ImportKind ik1; 132 ImportKind ik2; 133 QualifierKind qk1; 134 QualifierKind qk2; 135 NameKind nk1; 136 NameKind nk2; 137 JavaSource source; 138 DiagnosticChecker diagChecker; 139 140 TestDuplicateImport(ImportKind ik1, ImportKind ik2, QualifierKind qk1, QualifierKind qk2, NameKind nk1, NameKind nk2) { 141 this.ik1 = ik1; 142 this.ik2 = ik2; 143 this.qk1 = qk1; 144 this.qk2 = qk2; 145 this.nk1 = nk1; 146 this.nk2 = nk2; 147 this.source = new JavaSource(); 148 this.diagChecker = new DiagnosticChecker(); 149 } 150 class JavaSource extends SimpleJavaFileObject { 151 152 String bodyTemplate = "package a;\n" + 153 "#I1\n" + 154 "#I2\n" + 155 "class A {\n" + 156 " static class D { }\n" + 157 " static class E { }\n" + 158 " static Object f;\n" + 159 " static void m() { }\n" + 160 "}\n" + 161 "class B {\n" + 162 " static class D { }\n" + 163 " static class E { }\n" + 164 " static Object f;\n" + 165 " static void m() { }\n" + 166 "}\n" + 167 "class C extends B {\n" + 168 "}\n"; 169 170 String source; 171 172 public JavaSource() { 173 super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); 174 source = bodyTemplate.replaceAll("#I1", ik1.getImportStatement(qk1, nk1)) 175 .replaceAll("#I2", ik2.getImportStatement(qk2, nk2)); 176 } 177 178 @Override 179 public CharSequence getCharContent(boolean ignoreEncodingErrors) { 180 return source; 181 } 182 } 183 184 void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception { 185 JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker, 186 null, null, Arrays.asList(source)); 187 try { 188 ct.analyze(); 189 } catch (Throwable ex) { 190 throw new AssertionError("Error thrown when compiling the following code:\n" + source.getCharContent(true)); 191 } 192 check(); 193 } 194 195 void check() { 196 checkCount++; 197 198 boolean errorExpected = false; 199 200 //error if the import refers to a non-existent symbol 201 if (!nk1.exists() || !nk2.exists()) { 202 errorExpected = true; 203 } 204 205 //error if a non-static import refers to a non-type symbol 206 if ((nk1.isMember() && !ik1.isStatic()) || 207 (nk2.isMember() && !ik2.isStatic())) { 208 errorExpected = true; 209 } 210 211 //error if two single non-static (or one static and one non-static) 212 //imports import same names from different places 213 if (nk1 == nk2 && nk1 != NameKind.STAR && !qk1.compatible(qk2) && 214 (!ik1.isStatic() || !ik2.isStatic())) { 215 errorExpected = true; 216 } 217 218 if ((qk1 == QualifierKind.C && !ik1.isStatic() && nk1 != NameKind.STAR) || 219 (qk2 == QualifierKind.C && !ik2.isStatic() && nk2 != NameKind.STAR)) { 220 errorExpected = true; 221 } 222 223 if (errorExpected != diagChecker.errorFound) { 224 throw new Error("invalid diagnostics for source:\n" + 225 source.getCharContent(true) + 226 "\nFound error: " + diagChecker.errorFound + 227 "\nExpected error: " + errorExpected); 228 } 229 } 230 231 static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> { 232 233 boolean errorFound; 234 235 public void report(Diagnostic<? extends JavaFileObject> diagnostic) { 236 if (diagnostic.getKind() == Diagnostic.Kind.ERROR) { 237 errorFound = true; 238 } 239 } 240 } 241} 242