1 /*
   2  * Copyright (c) 2011, 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 /*
  26  * @test
  27  * @bug 6639645 7026414 7025809
  28  * @summary Modeling type implementing missing interfaces
  29  * @library ../../../../lib
  30  * @build JavacTestingAbstractProcessor TestMissingElement
  31  * @compile -proc:only -XprintRounds -processor TestMissingElement InvalidSource.java
  32  */
  33 
  34 import java.util.*;
  35 import javax.annotation.processing.*;
  36 import javax.lang.model.element.*;
  37 import javax.lang.model.type.*;
  38 import javax.lang.model.util.*;
  39 import static javax.tools.Diagnostic.Kind.*;
  40 import static JavacTestingAbstractProcessor.*;
  41 
  42 public class TestMissingElement extends JavacTestingAbstractProcessor {
  43     @Override
  44     public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
  45         for (TypeElement te: ElementFilter.typesIn(roundEnv.getRootElements())) {
  46             if (isSimpleName(te, "InvalidSource")) {
  47                 for (Element c: te.getEnclosedElements()) {
  48                     for (AnnotationMirror am: c.getAnnotationMirrors()) {
  49                         Element ate = am.getAnnotationType().asElement();
  50                         if (isSimpleName(ate, "ExpectInterfaces")) {
  51                             checkInterfaces((TypeElement) c, getValue(am));
  52                         } else if (isSimpleName(ate, "ExpectSupertype")) {
  53                             checkSupertype((TypeElement) c, getValue(am));
  54                         }
  55                     }
  56                 }
  57             }
  58         }
  59         return true;
  60     }
  61 
  62     private boolean isSimpleName(Element e, String name) {
  63         return e.getSimpleName().contentEquals(name);
  64     }
  65 
  66     private String getValue(AnnotationMirror am) {
  67         Map<? extends ExecutableElement, ? extends AnnotationValue> map = am.getElementValues();
  68         if (map.size() != 1) throw new IllegalArgumentException();
  69         AnnotationValue v = map.values().iterator().next();
  70         return (String) v.getValue();
  71     }
  72 
  73     private void checkInterfaces(TypeElement te, String expect) {
  74         System.err.println("check interfaces: " + te + " -- " + expect);
  75         String found = asString(te.getInterfaces(), ", ");
  76         checkEqual("interfaces", te, found, expect);
  77     }
  78 
  79     private void checkSupertype(TypeElement te, String expect) {
  80         System.err.println("check supertype: " + te + " -- " + expect);
  81         String found = asString(te.getSuperclass());
  82         checkEqual("supertype", te, found, expect);
  83     }
  84 
  85     private void checkEqual(String label, TypeElement te, String found, String expect) {
  86         if (found.equals(expect)) {
  87 //            messager.printMessage(NOTE, "expected " + label + " found: " + expect, te);
  88         } else {
  89             System.err.println("unexpected " + label + ": " + te + "\n"
  90                     + " found: " + found + "\n"
  91                     + "expect: " + expect);
  92             messager.printMessage(ERROR, "unexpected " + label + " found: " + found + "; expected: " + expect, te);
  93         }
  94     }
  95 
  96     private String asString(List<? extends TypeMirror> ts, String sep) {
  97         StringBuilder sb = new StringBuilder();
  98         for (TypeMirror t: ts) {
  99             if (sb.length() != 0) sb.append(sep);
 100             sb.append(asString(t));
 101         }
 102         return sb.toString();
 103     }
 104 
 105     private String asString(TypeMirror t) {
 106         if (t == null)
 107             return "[typ:null]";
 108         return t.accept(new SimpleTypeVisitor<String, Void>() {
 109             @Override
 110             public String defaultAction(TypeMirror t, Void ignore) {
 111                 return "[typ:" + t.toString() + "]";
 112             }
 113 
 114             @Override
 115             public String visitDeclared(DeclaredType t, Void ignore) {
 116                 checkEqual(t.asElement(), types.asElement(t));
 117                 String s = asString(t.asElement());
 118                 List<? extends TypeMirror> args = t.getTypeArguments();
 119                 if (!args.isEmpty())
 120                     s += "<" + asString(args, ",") + ">";
 121                 return s;
 122             }
 123 
 124             @Override
 125             public String visitTypeVariable(TypeVariable t, Void ignore) {
 126                 return "tvar " + t;
 127             }
 128 
 129             @Override
 130             public String visitError(ErrorType t, Void ignore) {
 131                 return "!:" + visitDeclared(t, ignore);
 132             }
 133         }, null);
 134     }
 135 
 136     private String asString(Element e) {
 137         if (e == null)
 138             return "[elt:null]";
 139         return e.accept(new SimpleElementVisitor<String, Void>() {
 140             @Override
 141             public String defaultAction(Element e, Void ignore) {
 142                 return "[elt:" + e.getKind() + " " + e.toString() + "]";
 143             }
 144             @Override
 145             public String visitPackage(PackageElement e, Void ignore) {
 146                 return "pkg " + e.getQualifiedName();
 147             }
 148             @Override
 149             public String visitType(TypeElement e, Void ignore) {
 150                 StringBuilder sb = new StringBuilder();
 151                 if (e.getEnclosedElements().isEmpty())
 152                     sb.append("empty ");
 153                 ElementKind ek = e.getKind();
 154                 switch (ek) {
 155                     case CLASS:
 156                         sb.append("clss");
 157                         break;
 158                     case INTERFACE:
 159                         sb.append("intf");
 160                         break;
 161                     default:
 162                         sb.append(ek);
 163                         break;
 164                 }
 165                 sb.append(" ");
 166                 Element encl = e.getEnclosingElement();
 167                 if (!isUnnamedPackage(encl) && encl.asType().getKind() != TypeKind.NONE) {
 168                     sb.append("(");
 169                     sb.append(asString(encl));
 170                     sb.append(")");
 171                     sb.append(".");
 172                 }
 173                 sb.append(e.getSimpleName());
 174                 if (e.asType().getKind() == TypeKind.ERROR) sb.append("!");
 175                 return sb.toString();
 176             }
 177         }, null);
 178     }
 179 
 180     boolean isUnnamedPackage(Element e) {
 181         return (e != null && e.getKind() == ElementKind.PACKAGE
 182                 && ((PackageElement) e).isUnnamed());
 183     }
 184 
 185     void checkEqual(Element e1, Element e2) {
 186         if (e1 != e2) {
 187             throw new AssertionError("elements not equal as expected: "
 188                 + e1 + ", " + e2);
 189         }
 190     }
 191 }
 192 
 193 
 194