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