jjg@904: /* jjg@1521: * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. jjg@904: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. jjg@904: * jjg@904: * This code is free software; you can redistribute it and/or modify it jjg@904: * under the terms of the GNU General Public License version 2 only, as jjg@904: * published by the Free Software Foundation. jjg@904: * jjg@904: * This code is distributed in the hope that it will be useful, but WITHOUT jjg@904: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or jjg@904: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License jjg@904: * version 2 for more details (a copy is included in the LICENSE file that jjg@904: * accompanied this code). jjg@904: * jjg@904: * You should have received a copy of the GNU General Public License version jjg@904: * 2 along with this work; if not, write to the Free Software Foundation, jjg@904: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. jjg@904: * jjg@904: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA jjg@904: * or visit www.oracle.com if you need additional information or have any jjg@904: * questions. jjg@904: */ jjg@904: jjg@904: jjg@904: /* jjg@904: * @test darcy@1054: * @bug 6639645 7026414 7025809 jjg@904: * @summary Modeling type implementing missing interfaces darcy@1466: * @library /tools/javac/lib jjg@904: * @build JavacTestingAbstractProcessor TestMissingElement jjg@1521: * @compile/fail/ref=TestMissingElement.ref -proc:only -XprintRounds -XDrawDiagnostics -processor TestMissingElement InvalidSource.java jjg@904: */ jjg@904: jjg@904: import java.util.*; jjg@904: import javax.annotation.processing.*; jjg@904: import javax.lang.model.element.*; jjg@904: import javax.lang.model.type.*; jjg@904: import javax.lang.model.util.*; jjg@904: import static javax.tools.Diagnostic.Kind.*; jjg@904: jjg@904: public class TestMissingElement extends JavacTestingAbstractProcessor { jjg@904: @Override jjg@904: public boolean process(Set annotations, RoundEnvironment roundEnv) { jjg@904: for (TypeElement te: ElementFilter.typesIn(roundEnv.getRootElements())) { jjg@904: if (isSimpleName(te, "InvalidSource")) { jjg@904: for (Element c: te.getEnclosedElements()) { jjg@904: for (AnnotationMirror am: c.getAnnotationMirrors()) { jjg@904: Element ate = am.getAnnotationType().asElement(); jjg@904: if (isSimpleName(ate, "ExpectInterfaces")) { jjg@904: checkInterfaces((TypeElement) c, getValue(am)); jjg@904: } else if (isSimpleName(ate, "ExpectSupertype")) { jjg@904: checkSupertype((TypeElement) c, getValue(am)); jjg@904: } jjg@904: } jjg@904: } jjg@904: } jjg@904: } jjg@904: return true; jjg@904: } jjg@904: jjg@904: private boolean isSimpleName(Element e, String name) { jjg@904: return e.getSimpleName().contentEquals(name); jjg@904: } jjg@904: jjg@904: private String getValue(AnnotationMirror am) { jjg@904: Map map = am.getElementValues(); jjg@904: if (map.size() != 1) throw new IllegalArgumentException(); jjg@904: AnnotationValue v = map.values().iterator().next(); jjg@904: return (String) v.getValue(); jjg@904: } jjg@904: jjg@904: private void checkInterfaces(TypeElement te, String expect) { jjg@904: System.err.println("check interfaces: " + te + " -- " + expect); jjg@904: String found = asString(te.getInterfaces(), ", "); jjg@904: checkEqual("interfaces", te, found, expect); jjg@904: } jjg@904: jjg@904: private void checkSupertype(TypeElement te, String expect) { jjg@904: System.err.println("check supertype: " + te + " -- " + expect); jjg@904: String found = asString(te.getSuperclass()); jjg@904: checkEqual("supertype", te, found, expect); jjg@904: } jjg@904: jjg@904: private void checkEqual(String label, TypeElement te, String found, String expect) { jjg@904: if (found.equals(expect)) { jjg@904: // messager.printMessage(NOTE, "expected " + label + " found: " + expect, te); jjg@904: } else { jjg@904: System.err.println("unexpected " + label + ": " + te + "\n" jjg@904: + " found: " + found + "\n" jjg@904: + "expect: " + expect); jjg@904: messager.printMessage(ERROR, "unexpected " + label + " found: " + found + "; expected: " + expect, te); jjg@904: } jjg@904: } jjg@904: jjg@904: private String asString(List ts, String sep) { jjg@904: StringBuilder sb = new StringBuilder(); jjg@904: for (TypeMirror t: ts) { jjg@904: if (sb.length() != 0) sb.append(sep); jjg@904: sb.append(asString(t)); jjg@904: } jjg@904: return sb.toString(); jjg@904: } jjg@904: jjg@904: private String asString(TypeMirror t) { jjg@904: if (t == null) jjg@904: return "[typ:null]"; darcy@1054: return t.accept(new SimpleTypeVisitor() { jjg@904: @Override jjg@904: public String defaultAction(TypeMirror t, Void ignore) { jjg@904: return "[typ:" + t.toString() + "]"; jjg@904: } jjg@904: jjg@904: @Override jjg@904: public String visitDeclared(DeclaredType t, Void ignore) { jjg@928: checkEqual(t.asElement(), types.asElement(t)); jjg@904: String s = asString(t.asElement()); jjg@904: List args = t.getTypeArguments(); jjg@904: if (!args.isEmpty()) jjg@904: s += "<" + asString(args, ",") + ">"; jjg@904: return s; jjg@904: } jjg@904: jjg@904: @Override jjg@904: public String visitTypeVariable(TypeVariable t, Void ignore) { jjg@904: return "tvar " + t; jjg@904: } jjg@904: jjg@904: @Override jjg@904: public String visitError(ErrorType t, Void ignore) { jjg@904: return "!:" + visitDeclared(t, ignore); jjg@904: } jjg@904: }, null); jjg@904: } jjg@904: jjg@904: private String asString(Element e) { jjg@904: if (e == null) jjg@904: return "[elt:null]"; darcy@1054: return e.accept(new SimpleElementVisitor() { jjg@904: @Override jjg@904: public String defaultAction(Element e, Void ignore) { jjg@904: return "[elt:" + e.getKind() + " " + e.toString() + "]"; jjg@904: } jjg@904: @Override jjg@904: public String visitPackage(PackageElement e, Void ignore) { jjg@904: return "pkg " + e.getQualifiedName(); jjg@904: } jjg@904: @Override jjg@904: public String visitType(TypeElement e, Void ignore) { jjg@904: StringBuilder sb = new StringBuilder(); jjg@904: if (e.getEnclosedElements().isEmpty()) jjg@904: sb.append("empty "); jjg@904: ElementKind ek = e.getKind(); jjg@904: switch (ek) { jjg@904: case CLASS: jjg@904: sb.append("clss"); jjg@904: break; jjg@904: case INTERFACE: jjg@904: sb.append("intf"); jjg@904: break; jjg@904: default: jjg@904: sb.append(ek); jjg@904: break; jjg@904: } jjg@904: sb.append(" "); jjg@904: Element encl = e.getEnclosingElement(); jjg@904: if (!isUnnamedPackage(encl) && encl.asType().getKind() != TypeKind.NONE) { jjg@904: sb.append("("); jjg@904: sb.append(asString(encl)); jjg@904: sb.append(")"); jjg@904: sb.append("."); jjg@904: } jjg@904: sb.append(e.getSimpleName()); jjg@904: if (e.asType().getKind() == TypeKind.ERROR) sb.append("!"); jjg@904: return sb.toString(); jjg@904: } jjg@904: }, null); jjg@904: } jjg@904: jjg@904: boolean isUnnamedPackage(Element e) { jjg@904: return (e != null && e.getKind() == ElementKind.PACKAGE jjg@904: && ((PackageElement) e).isUnnamed()); jjg@904: } jjg@928: jjg@928: void checkEqual(Element e1, Element e2) { jjg@928: if (e1 != e2) { jjg@928: throw new AssertionError("elements not equal as expected: " jjg@928: + e1 + ", " + e2); jjg@928: } jjg@928: } jjg@904: } jjg@904: jjg@904: jjg@904: