changeset 973:4baab658f357

6639645: Modeling type implementing missing interfaces Reviewed-by: darcy, mcimadamore
author jjg
date Wed, 02 Mar 2011 21:13:55 -0800
parents 3085d0089546
children e9b8fbb30f5a
files src/share/classes/com/sun/tools/javac/code/Flags.java src/share/classes/com/sun/tools/javac/code/Symbol.java src/share/classes/com/sun/tools/javac/code/Type.java src/share/classes/com/sun/tools/javac/code/Types.java src/share/classes/com/sun/tools/javac/comp/Attr.java src/share/classes/com/sun/tools/javac/comp/MemberEnter.java src/share/classes/com/sun/tools/javac/parser/JavacParser.java src/share/classes/com/sun/tools/javac/tree/JCTree.java src/share/classes/com/sun/tools/javac/tree/TreeCopier.java src/share/classes/com/sun/tools/javac/tree/TreeMaker.java test/tools/javac/api/6557752/T6557752.java test/tools/javac/processing/model/element/TestMissingElement/InvalidSource.java test/tools/javac/processing/model/element/TestMissingElement/TestMissingElement.java test/tools/javac/processing/model/element/TestMissingElement2/Generator.java test/tools/javac/processing/model/element/TestMissingElement2/TestMissingClass.java test/tools/javac/processing/model/element/TestMissingElement2/TestMissingGenericClass1.java test/tools/javac/processing/model/element/TestMissingElement2/TestMissingGenericClass2.java test/tools/javac/processing/model/element/TestMissingElement2/TestMissingGenericInterface1.java test/tools/javac/processing/model/element/TestMissingElement2/TestMissingGenericInterface2.java test/tools/javac/processing/model/element/TestMissingElement2/TestMissingInterface.java
diffstat 20 files changed, 846 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/tools/javac/code/Flags.java	Wed Mar 02 21:06:17 2011 -0800
+++ b/src/share/classes/com/sun/tools/javac/code/Flags.java	Wed Mar 02 21:13:55 2011 -0800
@@ -43,7 +43,7 @@
     private Flags() {} // uninstantiable
 
     public static String toString(long flags) {
-        StringBuffer buf = new StringBuffer();
+        StringBuilder buf = new StringBuilder();
         String sep = "";
         for (Flag s : asFlagSet(flags)) {
             buf.append(sep);
--- a/src/share/classes/com/sun/tools/javac/code/Symbol.java	Wed Mar 02 21:06:17 2011 -0800
+++ b/src/share/classes/com/sun/tools/javac/code/Symbol.java	Wed Mar 02 21:13:55 2011 -0800
@@ -831,6 +831,8 @@
                 ClassType t = (ClassType)type;
                 if (t.interfaces_field == null) // FIXME: shouldn't be null
                     t.interfaces_field = List.nil();
+                if (t.all_interfaces_field != null)
+                    return Type.getModelTypes(t.all_interfaces_field);
                 return t.interfaces_field;
             } else {
                 return List.nil();
@@ -846,7 +848,7 @@
                 // An interface has no superclass; its supertype is Object.
                 return t.isInterface()
                     ? Type.noType
-                    : t.supertype_field;
+                    : t.supertype_field.getModelType();
             } else {
                 return Type.noType;
             }
--- a/src/share/classes/com/sun/tools/javac/code/Type.java	Wed Mar 02 21:06:17 2011 -0800
+++ b/src/share/classes/com/sun/tools/javac/code/Type.java	Wed Mar 02 21:13:55 2011 -0800
@@ -93,6 +93,22 @@
         return null;
     }
 
+    /**
+     * Get the representation of this type used for modelling purposes.
+     * By default, this is itself. For ErrorType, a different value
+     * may be provided,
+     */
+    public Type getModelType() {
+        return this;
+    }
+
+    public static List<Type> getModelTypes(List<Type> ts) {
+        ListBuffer<Type> lb = new ListBuffer<Type>();
+        for (Type t: ts)
+            lb.append(t.getModelType());
+        return lb.toList();
+    }
+
     public <R,S> R accept(Type.Visitor<R,S> v, S s) { return v.visitType(this, s); }
 
     /** Define a type given its tag and type symbol
@@ -190,7 +206,7 @@
         if (ts.isEmpty()) {
             return "";
         } else {
-            StringBuffer buf = new StringBuffer();
+            StringBuilder buf = new StringBuilder();
             buf.append(ts.head.toString());
             for (List<Type> l = ts.tail; l.nonEmpty(); l = l.tail)
                 buf.append(",").append(l.head.toString());
@@ -464,7 +480,7 @@
 
         boolean isPrintingBound = false;
         public String toString() {
-            StringBuffer s = new StringBuffer();
+            StringBuilder s = new StringBuilder();
             s.append(kind.toString());
             if (kind != UNBOUND)
                 s.append(type);
@@ -538,6 +554,10 @@
          */
         public List<Type> interfaces_field;
 
+        /** All the interfaces of this class, including missing ones.
+         */
+        public List<Type> all_interfaces_field;
+
         public ClassType(Type outer, List<Type> typarams, TypeSymbol tsym) {
             super(CLASS, tsym);
             this.outer_field = outer;
@@ -578,7 +598,7 @@
         /** The Java source which this type represents.
          */
         public String toString() {
-            StringBuffer buf = new StringBuffer();
+            StringBuilder buf = new StringBuilder();
             if (getEnclosingType().tag == CLASS && tsym.owner.kind == TYP) {
                 buf.append(getEnclosingType().toString());
                 buf.append(".");
@@ -596,7 +616,7 @@
 //where
             private String className(Symbol sym, boolean longform) {
                 if (sym.name.isEmpty() && (sym.flags() & COMPOUND) != 0) {
-                    StringBuffer s = new StringBuffer(supertype_field.toString());
+                    StringBuilder s = new StringBuilder(supertype_field.toString());
                     for (List<Type> is=interfaces_field; is.nonEmpty(); is = is.tail) {
                         s.append("&");
                         s.append(is.head.toString());
--- a/src/share/classes/com/sun/tools/javac/code/Types.java	Wed Mar 02 21:06:17 2011 -0800
+++ b/src/share/classes/com/sun/tools/javac/code/Types.java	Wed Mar 02 21:13:55 2011 -0800
@@ -2534,7 +2534,7 @@
     }
     // where
         private String typaramsString(List<Type> tvars) {
-            StringBuffer s = new StringBuffer();
+            StringBuilder s = new StringBuilder();
             s.append('<');
             boolean first = true;
             for (Type t : tvars) {
@@ -2545,7 +2545,7 @@
             s.append('>');
             return s.toString();
         }
-        private void appendTyparamString(TypeVar t, StringBuffer buf) {
+        private void appendTyparamString(TypeVar t, StringBuilder buf) {
             buf.append(t);
             if (t.bound == null ||
                 t.bound.tsym.getQualifiedName() == names.java_lang_Object)
--- a/src/share/classes/com/sun/tools/javac/comp/Attr.java	Wed Mar 02 21:06:17 2011 -0800
+++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java	Wed Mar 02 21:13:55 2011 -0800
@@ -2980,7 +2980,7 @@
             // (see comment for TypeVar.bound).
             // In this case, generate a class tree that represents the
             // bound class, ...
-            JCTree extending;
+            JCExpression extending;
             List<JCExpression> implementing;
             if ((bs.head.tsym.flags() & INTERFACE) == 0) {
                 extending = tree.bounds.head;
--- a/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java	Wed Mar 02 21:06:17 2011 -0800
+++ b/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java	Wed Mar 02 21:13:55 2011 -0800
@@ -889,10 +889,11 @@
                 : (c.fullname == names.java_lang_Object)
                 ? Type.noType
                 : syms.objectType;
-            ct.supertype_field = supertype;
+            ct.supertype_field = modelMissingTypes(supertype, tree.extending, false);
 
             // Determine interfaces.
             ListBuffer<Type> interfaces = new ListBuffer<Type>();
+            ListBuffer<Type> all_interfaces = null; // lazy init
             Set<Type> interfaceSet = new HashSet<Type>();
             List<JCExpression> interfaceTrees = tree.implementing;
             if ((tree.mods.flags & Flags.ENUM) != 0 && target.compilerBootstrap(c)) {
@@ -909,13 +910,22 @@
                 Type i = attr.attribBase(iface, baseEnv, false, true, true);
                 if (i.tag == CLASS) {
                     interfaces.append(i);
+                    if (all_interfaces != null) all_interfaces.append(i);
                     chk.checkNotRepeated(iface.pos(), types.erasure(i), interfaceSet);
+                } else {
+                    if (all_interfaces == null)
+                        all_interfaces = new ListBuffer<Type>().appendList(interfaces);
+                    all_interfaces.append(modelMissingTypes(i, iface, true));
                 }
             }
-            if ((c.flags_field & ANNOTATION) != 0)
+            if ((c.flags_field & ANNOTATION) != 0) {
                 ct.interfaces_field = List.of(syms.annotationType);
-            else
+                ct.all_interfaces_field = ct.interfaces_field;
+            }  else {
                 ct.interfaces_field = interfaces.toList();
+                ct.all_interfaces_field = (all_interfaces == null)
+                        ? ct.interfaces_field : all_interfaces.toList();
+            }
 
             if (c.fullname == names.java_lang_Object) {
                 if (tree.extending != null) {
@@ -1066,6 +1076,125 @@
         return result;
     }
 
+    Type modelMissingTypes(Type t, final JCExpression tree, final boolean interfaceExpected) {
+        if (t.tag != ERROR)
+            return t;
+
+        return new ErrorType(((ErrorType) t).getOriginalType(), t.tsym) {
+            private Type modelType;
+
+            @Override
+            public Type getModelType() {
+                if (modelType == null)
+                    modelType = new Synthesizer(getOriginalType(), interfaceExpected).visit(tree);
+                return modelType;
+            }
+        };
+    }
+    // where
+    private class Synthesizer extends JCTree.Visitor {
+        Type originalType;
+        boolean interfaceExpected;
+        List<ClassSymbol> synthesizedSymbols = List.nil();
+        Type result;
+
+        Synthesizer(Type originalType, boolean interfaceExpected) {
+            this.originalType = originalType;
+            this.interfaceExpected = interfaceExpected;
+        }
+
+        Type visit(JCTree tree) {
+            tree.accept(this);
+            return result;
+        }
+
+        List<Type> visit(List<? extends JCTree> trees) {
+            ListBuffer<Type> lb = new ListBuffer<Type>();
+            for (JCTree t: trees)
+                lb.append(visit(t));
+            return lb.toList();
+        }
+
+        @Override
+        public void visitTree(JCTree tree) {
+            result = syms.errType;
+        }
+
+        @Override
+        public void visitIdent(JCIdent tree) {
+            if (tree.type.tag != ERROR) {
+                result = tree.type;
+            } else {
+                result = synthesizeClass(tree.name, syms.unnamedPackage).type;
+            }
+        }
+
+        @Override
+        public void visitSelect(JCFieldAccess tree) {
+            if (tree.type.tag != ERROR) {
+                result = tree.type;
+            } else {
+                Type selectedType;
+                boolean prev = interfaceExpected;
+                try {
+                    interfaceExpected = false;
+                    selectedType = visit(tree.selected);
+                } finally {
+                    interfaceExpected = prev;
+                }
+                ClassSymbol c = synthesizeClass(tree.name, selectedType.tsym);
+                result = c.type;
+            }
+        }
+
+        @Override
+        public void visitTypeApply(JCTypeApply tree) {
+            if (tree.type.tag != ERROR) {
+                result = tree.type;
+            } else {
+                ClassType clazzType = (ClassType) visit(tree.clazz);
+                if (synthesizedSymbols.contains(clazzType.tsym))
+                    synthesizeTyparams((ClassSymbol) clazzType.tsym, tree.arguments.size());
+                final List<Type> actuals = visit(tree.arguments);
+                result = new ErrorType(tree.type, clazzType.tsym) {
+                    @Override
+                    public List<Type> getTypeArguments() {
+                        return actuals;
+                    }
+                };
+            }
+        }
+
+        ClassSymbol synthesizeClass(Name name, Symbol owner) {
+            int flags = interfaceExpected ? INTERFACE : 0;
+            ClassSymbol c = new ClassSymbol(flags, name, owner);
+            c.members_field = new Scope.ErrorScope(c);
+            c.type = new ErrorType(originalType, c) {
+                @Override
+                public List<Type> getTypeArguments() {
+                    return typarams_field;
+                }
+            };
+            synthesizedSymbols = synthesizedSymbols.prepend(c);
+            return c;
+        }
+
+        void synthesizeTyparams(ClassSymbol sym, int n) {
+            ClassType ct = (ClassType) sym.type;
+            Assert.check(ct.typarams_field.isEmpty());
+            if (n == 1) {
+                TypeVar v = new TypeVar(names.fromString("T"), sym, syms.botType);
+                ct.typarams_field = ct.typarams_field.prepend(v);
+            } else {
+                for (int i = n; i > 0; i--) {
+                    TypeVar v = new TypeVar(names.fromString("T" + i), sym, syms.botType);
+                    ct.typarams_field = ct.typarams_field.prepend(v);
+                }
+            }
+        }
+    }
+
+
 /* ***************************************************************************
  * tree building
  ****************************************************************************/
--- a/src/share/classes/com/sun/tools/javac/parser/JavacParser.java	Wed Mar 02 21:06:17 2011 -0800
+++ b/src/share/classes/com/sun/tools/javac/parser/JavacParser.java	Wed Mar 02 21:13:55 2011 -0800
@@ -2357,7 +2357,7 @@
 
         List<JCTypeParameter> typarams = typeParametersOpt();
 
-        JCTree extending = null;
+        JCExpression extending = null;
         if (S.token() == EXTENDS) {
             S.nextToken();
             extending = parseType();
--- a/src/share/classes/com/sun/tools/javac/tree/JCTree.java	Wed Mar 02 21:06:17 2011 -0800
+++ b/src/share/classes/com/sun/tools/javac/tree/JCTree.java	Wed Mar 02 21:13:55 2011 -0800
@@ -567,14 +567,14 @@
         public JCModifiers mods;
         public Name name;
         public List<JCTypeParameter> typarams;
-        public JCTree extending;
+        public JCExpression extending;
         public List<JCExpression> implementing;
         public List<JCTree> defs;
         public ClassSymbol sym;
         protected JCClassDecl(JCModifiers mods,
                            Name name,
                            List<JCTypeParameter> typarams,
-                           JCTree extending,
+                           JCExpression extending,
                            List<JCExpression> implementing,
                            List<JCTree> defs,
                            ClassSymbol sym)
@@ -2104,7 +2104,7 @@
         JCClassDecl ClassDef(JCModifiers mods,
                           Name name,
                           List<JCTypeParameter> typarams,
-                          JCTree extending,
+                          JCExpression extending,
                           List<JCExpression> implementing,
                           List<JCTree> defs);
         JCMethodDecl MethodDef(JCModifiers mods,
--- a/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java	Wed Mar 02 21:06:17 2011 -0800
+++ b/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java	Wed Mar 02 21:13:55 2011 -0800
@@ -135,7 +135,7 @@
         JCClassDecl t = (JCClassDecl) node;
         JCModifiers mods = copy(t.mods, p);
         List<JCTypeParameter> typarams = copy(t.typarams, p);
-        JCTree extending = copy(t.extending, p);
+        JCExpression extending = copy(t.extending, p);
         List<JCExpression> implementing = copy(t.implementing, p);
         List<JCTree> defs = copy(t.defs, p);
         return M.at(t.pos).ClassDef(mods, t.name, typarams, extending, implementing, defs);
--- a/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java	Wed Mar 02 21:06:17 2011 -0800
+++ b/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java	Wed Mar 02 21:13:55 2011 -0800
@@ -146,7 +146,7 @@
     public JCClassDecl ClassDef(JCModifiers mods,
                                 Name name,
                                 List<JCTypeParameter> typarams,
-                                JCTree extending,
+                                JCExpression extending,
                                 List<JCExpression> implementing,
                                 List<JCTree> defs)
     {
--- a/test/tools/javac/api/6557752/T6557752.java	Wed Mar 02 21:06:17 2011 -0800
+++ b/test/tools/javac/api/6557752/T6557752.java	Wed Mar 02 21:13:55 2011 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -119,7 +119,7 @@
                 Types types = task.getTypes();
 
                 if (types.asElement(trees.getOriginalType((ErrorType)typeMirror)) != null) {
-                    throw new AssertionError("Ttypes.asElement() error!");
+                    throw new AssertionError("Types.asElement() error!");
                 }
                 foundError = true;
               }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/processing/model/element/TestMissingElement/InvalidSource.java	Wed Mar 02 21:13:55 2011 -0800
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.util.*;
+
+@interface ExpectInterfaces {
+    String value();
+}
+
+@interface ExpectSupertype {
+    String value();
+}
+
+interface OK {
+    void m();
+}
+
+class InvalidSource {
+    /*
+     * The following annotations contain a simple description of the expected
+     * representation of the superclass and superinterfaces of the corresponding
+     * elements.
+     * The strings contain a comma-separated list of descriptions.
+     * Descriptions are composed as follows:
+     * A leading "!:" indicates the type mirror has kind ERROR.
+     * "empty" means that the corresponding element has no enclosed elements.
+     * "clss", "intf" and "tvar" indicate the name refers to a class, interface
+     * or type variable. Each is followed by the declared name of the element.
+     * "pkg" indicates the name of a package element.
+     * An enclosing element is shown in parentheses.
+     * A trailing "!" indicates that the element's type has kind ERROR.
+     */
+
+    @ExpectSupertype("!:empty clss A!")
+    class TestClassMissingClassA extends A { }
+
+    @ExpectSupertype("!:empty clss (pkg A).B!")
+    class TestClassMissingClassAB extends A.B { }
+
+    @ExpectSupertype("!:empty clss (pkg java.util).A!")
+    class TestClassMissingClass_juA extends java.util.A { }
+
+    @ExpectSupertype("!:empty clss A!<tvar T>")
+    class TestClassTMissingClassAT<T> extends A<T> { }
+
+    @ExpectInterfaces("!:empty intf A!")
+    class TestClassMissingIntfA implements A { }
+
+    @ExpectInterfaces("!:empty intf (pkg A).B!")
+    class TestClassMissingIntfAB implements A.B { }
+
+    @ExpectInterfaces("!:empty intf A!, intf OK")
+    abstract class TestClassMissingIntfAOK implements A, OK { }
+
+    @ExpectInterfaces("intf OK, !:empty intf A!")
+    abstract class TestClassOKMissingIntfA implements OK, A { }
+
+    @ExpectInterfaces("!:empty intf A!, !:empty intf B!")
+    class TestClassMissingIntfA_B implements A, B { }
+
+    @ExpectInterfaces("!:empty intf A!")
+    interface TestIntfMissingIntfA extends A { }
+
+    @ExpectInterfaces("!:empty intf A!, intf OK")
+    interface TestIntfMissingIntfAOK extends A, OK { }
+
+    @ExpectInterfaces("intf OK, !:empty intf A!")
+    interface TestIntfOKMissingIntfA extends OK, A { }
+
+    @ExpectInterfaces("!:empty intf A!, !:empty intf B!")
+    interface TestIntfMissingIntfAB extends A, B { }
+
+    @ExpectInterfaces("!:empty intf A!<tvar T>")
+    class TestClassTMissingIntfAT<T> implements A<T> { }
+
+    @ExpectInterfaces("!:empty intf A!<tvar T>, !:empty intf B!")
+    class TestClassTMissingIntfAT_B<T> implements A<T>, B { }
+
+    @ExpectInterfaces("!:empty intf A!<tvar T>")
+    interface TestIntfTMissingIntfAT<T> extends A<T> { }
+
+    @ExpectInterfaces("!:empty intf A!<tvar T>, !:empty intf B!")
+    interface TestIntfTMissingIntfAT_B<T> extends A<T>, B { }
+
+    @ExpectInterfaces("intf (pkg java.util).List<!:empty clss X!>")
+    abstract class TestClassListMissingX implements List<X> { }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/processing/model/element/TestMissingElement/TestMissingElement.java	Wed Mar 02 21:13:55 2011 -0800
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/*
+ * @test
+ * @bug 6639645
+ * @summary Modeling type implementing missing interfaces
+ * @library ../../../../lib
+ * @build JavacTestingAbstractProcessor TestMissingElement
+ * @compile -proc:only -XprintRounds -processor TestMissingElement InvalidSource.java
+ */
+
+import java.util.*;
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+import static javax.tools.Diagnostic.Kind.*;
+
+public class TestMissingElement extends JavacTestingAbstractProcessor {
+    @Override
+    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+        for (TypeElement te: ElementFilter.typesIn(roundEnv.getRootElements())) {
+            if (isSimpleName(te, "InvalidSource")) {
+                for (Element c: te.getEnclosedElements()) {
+                    for (AnnotationMirror am: c.getAnnotationMirrors()) {
+                        Element ate = am.getAnnotationType().asElement();
+                        if (isSimpleName(ate, "ExpectInterfaces")) {
+                            checkInterfaces((TypeElement) c, getValue(am));
+                        } else if (isSimpleName(ate, "ExpectSupertype")) {
+                            checkSupertype((TypeElement) c, getValue(am));
+                        }
+                    }
+                }
+            }
+        }
+        return true;
+    }
+
+    private boolean isSimpleName(Element e, String name) {
+        return e.getSimpleName().contentEquals(name);
+    }
+
+    private String getValue(AnnotationMirror am) {
+        Map<? extends ExecutableElement, ? extends AnnotationValue> map = am.getElementValues();
+        if (map.size() != 1) throw new IllegalArgumentException();
+        AnnotationValue v = map.values().iterator().next();
+        return (String) v.getValue();
+    }
+
+    private void checkInterfaces(TypeElement te, String expect) {
+        System.err.println("check interfaces: " + te + " -- " + expect);
+        String found = asString(te.getInterfaces(), ", ");
+        checkEqual("interfaces", te, found, expect);
+    }
+
+    private void checkSupertype(TypeElement te, String expect) {
+        System.err.println("check supertype: " + te + " -- " + expect);
+        String found = asString(te.getSuperclass());
+        checkEqual("supertype", te, found, expect);
+    }
+
+    private void checkEqual(String label, TypeElement te, String found, String expect) {
+        if (found.equals(expect)) {
+//            messager.printMessage(NOTE, "expected " + label + " found: " + expect, te);
+        } else {
+            System.err.println("unexpected " + label + ": " + te + "\n"
+                    + " found: " + found + "\n"
+                    + "expect: " + expect);
+            messager.printMessage(ERROR, "unexpected " + label + " found: " + found + "; expected: " + expect, te);
+        }
+    }
+
+    private String asString(List<? extends TypeMirror> ts, String sep) {
+        StringBuilder sb = new StringBuilder();
+        for (TypeMirror t: ts) {
+            if (sb.length() != 0) sb.append(sep);
+            sb.append(asString(t));
+        }
+        return sb.toString();
+    }
+
+    private String asString(TypeMirror t) {
+        if (t == null)
+            return "[typ:null]";
+        return t.accept(new SimpleTypeVisitor7<String, Void>() {
+            @Override
+            public String defaultAction(TypeMirror t, Void ignore) {
+                return "[typ:" + t.toString() + "]";
+            }
+
+            @Override
+            public String visitDeclared(DeclaredType t, Void ignore) {
+                String s = asString(t.asElement());
+                List<? extends TypeMirror> args = t.getTypeArguments();
+                if (!args.isEmpty())
+                    s += "<" + asString(args, ",") + ">";
+                return s;
+            }
+
+            @Override
+            public String visitTypeVariable(TypeVariable t, Void ignore) {
+                return "tvar " + t;
+            }
+
+            @Override
+            public String visitError(ErrorType t, Void ignore) {
+                return "!:" + visitDeclared(t, ignore);
+            }
+        }, null);
+    }
+
+    private String asString(Element e) {
+        if (e == null)
+            return "[elt:null]";
+        return e.accept(new SimpleElementVisitor7<String, Void>() {
+            @Override
+            public String defaultAction(Element e, Void ignore) {
+                return "[elt:" + e.getKind() + " " + e.toString() + "]";
+            }
+            @Override
+            public String visitPackage(PackageElement e, Void ignore) {
+                return "pkg " + e.getQualifiedName();
+            }
+            @Override
+            public String visitType(TypeElement e, Void ignore) {
+                StringBuilder sb = new StringBuilder();
+                if (e.getEnclosedElements().isEmpty())
+                    sb.append("empty ");
+                ElementKind ek = e.getKind();
+                switch (ek) {
+                    case CLASS:
+                        sb.append("clss");
+                        break;
+                    case INTERFACE:
+                        sb.append("intf");
+                        break;
+                    default:
+                        sb.append(ek);
+                        break;
+                }
+                sb.append(" ");
+                Element encl = e.getEnclosingElement();
+                if (!isUnnamedPackage(encl) && encl.asType().getKind() != TypeKind.NONE) {
+                    sb.append("(");
+                    sb.append(asString(encl));
+                    sb.append(")");
+                    sb.append(".");
+                }
+                sb.append(e.getSimpleName());
+                if (e.asType().getKind() == TypeKind.ERROR) sb.append("!");
+                return sb.toString();
+            }
+        }, null);
+    }
+
+    boolean isUnnamedPackage(Element e) {
+        return (e != null && e.getKind() == ElementKind.PACKAGE
+                && ((PackageElement) e).isUnnamed());
+    }
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/processing/model/element/TestMissingElement2/Generator.java	Wed Mar 02 21:13:55 2011 -0800
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.*;
+import java.util.*;
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+import javax.tools.*;
+
+public class Generator extends JavacTestingAbstractProcessor {
+
+    @Override
+    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+        for (TypeElement te: ElementFilter.typesIn(roundEnv.getRootElements())) {
+            System.err.println(te);
+            generateIfMissing(te.getSuperclass());
+            generateIfMissing(te.getInterfaces());
+        }
+        return true;
+    }
+
+    void generateIfMissing(List<? extends TypeMirror> ts) {
+        for (TypeMirror t: ts)
+            generateIfMissing(t);
+    }
+
+    void generateIfMissing(TypeMirror t) {
+        if (t == null)
+            return;
+        if (t.getKind() == TypeKind.ERROR) {
+            Element e = ((ErrorType) t).asElement();
+            if (e == null)
+                return;
+            if (e.asType().getKind() == TypeKind.ERROR)
+                createFile((TypeElement) e);
+        }
+    }
+
+    void createFile(TypeElement e) {
+        try {
+            JavaFileObject fo = filer.createSourceFile(e.getSimpleName());
+            Writer out = fo.openWriter();
+            try {
+                switch (e.getKind()) {
+                    case CLASS:
+                        out.write("import java.util.*;\n");
+                        out.write("class " + signature(e) + " {\n");
+                        out.write("    public void run() {\n");
+                        out.write("        Class<?> c = getClass();\n");
+                        out.write("        System.out.println(\"class: \" + c);\n");
+                        out.write("        System.out.println(\"superclass: \" + c.getSuperclass());\n");
+                        out.write("        System.out.println(\"generic superclass: \" +c.getGenericSuperclass());\n");
+                        out.write("        System.out.println(\"interfaces: \" + Arrays.asList(c.getInterfaces()));\n");
+                        out.write("        System.out.println(\"generic interfaces: \" + Arrays.asList(c.getGenericInterfaces()));\n");
+                        out.write("    }\n");
+                        out.write("}\n");
+                        break;
+                    case INTERFACE:
+                        out.write("interface " + signature(e) + " {\n");
+                        out.write("    void run();\n");
+                        out.write("}\n");
+                        break;
+                }
+            } finally {
+                out.close();
+            }
+        } catch (IOException ex) {
+            messager.printMessage(Diagnostic.Kind.ERROR, "problem writing file: " + ex);
+        }
+    }
+
+    String signature(TypeElement e) {
+        System.err.println("signature: " + e + " " + e.getTypeParameters());
+        StringBuilder sb = new StringBuilder();
+        sb.append(e.getSimpleName());
+        if (!e.getTypeParameters().isEmpty()) {
+            sb.append("<");
+            String sep = "";
+            for (TypeParameterElement t : e.getTypeParameters()) {
+                sb.append(sep);
+                sb.append(t);
+                sep = ",";
+            }
+            sb.append(">");
+        }
+        return sb.toString();
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/processing/model/element/TestMissingElement2/TestMissingClass.java	Wed Mar 02 21:13:55 2011 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6639645
+ * @summary Modeling type implementing missing interfaces
+ * @library ../../../../lib
+ * @build JavacTestingAbstractProcessor Generator
+ * @compile -XprintRounds -processor Generator TestMissingClass.java
+ * @run main TestMissingClass
+ */
+
+public class TestMissingClass extends MissingClass {
+    public static void main(String... args) {
+        new TestMissingClass().run();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/processing/model/element/TestMissingElement2/TestMissingGenericClass1.java	Wed Mar 02 21:13:55 2011 -0800
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6639645
+ * @summary Modeling type implementing missing interfaces
+ * @library ../../../../lib
+ * @clean MissingGenericClass1
+ * @build JavacTestingAbstractProcessor Generator
+ * @compile -XprintRounds -processor Generator TestMissingGenericClass1.java
+ * @run main TestMissingGenericClass1
+ */
+
+public class TestMissingGenericClass1 extends MissingGenericClass1<String> {
+    public static void main(String... args) {
+        new TestMissingGenericClass1().run();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/processing/model/element/TestMissingElement2/TestMissingGenericClass2.java	Wed Mar 02 21:13:55 2011 -0800
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6639645
+ * @summary Modeling type implementing missing interfaces
+ * @library ../../../../lib
+ * @clean MissingGenericClass2
+ * @build JavacTestingAbstractProcessor Generator
+ * @compile -XprintRounds -processor Generator TestMissingGenericClass2.java
+ * @run main TestMissingGenericClass2
+ */
+
+public class TestMissingGenericClass2 extends MissingGenericClass2<String,Integer> {
+    public static void main(String... args) {
+        new TestMissingGenericClass2().run();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/processing/model/element/TestMissingElement2/TestMissingGenericInterface1.java	Wed Mar 02 21:13:55 2011 -0800
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, asrm
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6639645
+ * @summary Modeling type implementing missing interfaces
+ * @library ../../../../lib
+ * @clean MissingGenericInterface1
+ * @build JavacTestingAbstractProcessor Generator
+ * @compile -XprintRounds -processor Generator TestMissingGenericInterface1.java
+ * @run main TestMissingGenericInterface1
+ */
+
+import java.util.*;
+
+public class TestMissingGenericInterface1 implements MissingGenericInterface1<String> {
+    public static void main(String... args) {
+        new TestMissingGenericInterface1().run();
+    }
+
+    @Override
+    public void run() {
+        Class<?> c = getClass();
+        System.out.println("class: " + c);
+        System.out.println("superclass: " + c.getSuperclass());
+        System.out.println("generic superclass: " +c.getGenericSuperclass());
+        System.out.println("interfaces: " + Arrays.asList(c.getInterfaces()));
+        System.out.println("generic interfaces: " + Arrays.asList(c.getGenericInterfaces()));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/processing/model/element/TestMissingElement2/TestMissingGenericInterface2.java	Wed Mar 02 21:13:55 2011 -0800
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, asrm
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6639645
+ * @summary Modeling type implementing missing interfaces
+ * @library ../../../../lib
+ * @clean MissingGenericInterface2
+ * @build JavacTestingAbstractProcessor Generator
+ * @compile -XprintRounds -processor Generator TestMissingGenericInterface2.java
+ * @run main TestMissingGenericInterface2
+ */
+
+import java.util.*;
+
+public class TestMissingGenericInterface2 implements MissingGenericInterface2<Integer,String> {
+    public static void main(String... args) {
+        new TestMissingGenericInterface2().run();
+    }
+
+    @Override
+    public void run() {
+        Class<?> c = getClass();
+        System.out.println("class: " + c);
+        System.out.println("superclass: " + c.getSuperclass());
+        System.out.println("generic superclass: " +c.getGenericSuperclass());
+        System.out.println("interfaces: " + Arrays.asList(c.getInterfaces()));
+        System.out.println("generic interfaces: " + Arrays.asList(c.getGenericInterfaces()));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/processing/model/element/TestMissingElement2/TestMissingInterface.java	Wed Mar 02 21:13:55 2011 -0800
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, asrm
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6639645
+ * @summary Modeling type implementing missing interfaces
+ * @library ../../../../lib
+ * @build JavacTestingAbstractProcessor Generator
+ * @compile -XprintRounds -processor Generator TestMissingInterface.java
+ * @run main TestMissingInterface
+ */
+
+import java.util.*;
+
+public class TestMissingInterface implements MissingInterface {
+    public static void main(String... args) {
+        new TestMissingInterface().run();
+    }
+
+    @Override
+    public void run() {
+        Class<?> c = getClass();
+        System.out.println("class: " + c);
+        System.out.println("superclass: " + c.getSuperclass());
+        System.out.println("generic superclass: " +c.getGenericSuperclass());
+        System.out.println("interfaces: " + Arrays.asList(c.getInterfaces()));
+        System.out.println("generic interfaces: " + Arrays.asList(c.getGenericInterfaces()));
+    }
+
+}