changeset 111:91eea580fbe9

6557752: Original type of an AST should be made available even if it is replaced with an ErrorType Reviewed-by: mcimadamore
author jjg
date Tue, 09 Sep 2008 10:28:21 -0700
parents 5a9b808557b6
children a92b756a888f
files src/share/classes/com/sun/source/util/Trees.java src/share/classes/com/sun/tools/javac/api/JavacTrees.java src/share/classes/com/sun/tools/javac/code/Symbol.java src/share/classes/com/sun/tools/javac/code/Symtab.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/Check.java src/share/classes/com/sun/tools/javac/comp/Enter.java src/share/classes/com/sun/tools/javac/comp/Infer.java src/share/classes/com/sun/tools/javac/comp/Resolve.java src/share/classes/javax/lang/model/type/ErrorType.java test/tools/javac/api/6557752/T6557752.java
diffstat 13 files changed, 228 insertions(+), 52 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/source/util/Trees.java	Thu Sep 04 14:56:35 2008 -0700
+++ b/src/share/classes/com/sun/source/util/Trees.java	Tue Sep 09 10:28:21 2008 -0700
@@ -33,6 +33,7 @@
 import javax.lang.model.element.ExecutableElement;
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.ErrorType;
 import javax.lang.model.type.TypeMirror;
 import javax.tools.JavaCompiler.CompilationTask;
 
@@ -177,4 +178,11 @@
      * @return true if {@code member} is accessible in {@code type}
      */
     public abstract boolean isAccessible(Scope scope, Element member, DeclaredType type);
+
+    /**
+      * Gets the original type from the ErrorType object.
+      * @param errorType The errorType for which we want to get the original type.
+      * @returns javax.lang.model.type.TypeMirror corresponding to the original type, replaced by the ErrorType.
+      */
+    public abstract TypeMirror getOriginalType(ErrorType errorType);
 }
--- a/src/share/classes/com/sun/tools/javac/api/JavacTrees.java	Thu Sep 04 14:56:35 2008 -0700
+++ b/src/share/classes/com/sun/tools/javac/api/JavacTrees.java	Tue Sep 09 10:28:21 2008 -0700
@@ -322,4 +322,18 @@
             return t2;
         }
     }
+
+    /**
+     * Gets the original type from the ErrorType object.
+     * @param errorType The errorType for which we want to get the original type.
+     * @returns TypeMirror corresponding to the original type, replaced by the ErrorType.
+     *          noType (type.tag == NONE) is returned if there is no original type.
+     */
+    public TypeMirror getOriginalType(javax.lang.model.type.ErrorType errorType) {
+        if (errorType instanceof com.sun.tools.javac.code.Type.ErrorType) {
+            return ((com.sun.tools.javac.code.Type.ErrorType)errorType).getOriginalType();
+        }
+
+        return com.sun.tools.javac.code.Type.noType;
+    }
 }
--- a/src/share/classes/com/sun/tools/javac/code/Symbol.java	Thu Sep 04 14:56:35 2008 -0700
+++ b/src/share/classes/com/sun/tools/javac/code/Symbol.java	Tue Sep 09 10:28:21 2008 -0700
@@ -776,7 +776,7 @@
             } catch (CompletionFailure ex) {
                 // quiet error recovery
                 flags_field |= (PUBLIC|STATIC);
-                this.type = new ErrorType(this);
+                this.type = new ErrorType(this, Type.noType);
                 throw ex;
             }
         }
--- a/src/share/classes/com/sun/tools/javac/code/Symtab.java	Thu Sep 04 14:56:35 2008 -0700
+++ b/src/share/classes/com/sun/tools/javac/code/Symtab.java	Tue Sep 09 10:28:21 2008 -0700
@@ -93,8 +93,7 @@
      */
     public final ClassSymbol errSymbol;
 
-    /** An instance of the error type.
-     */
+    /** A value for the errType, with a originalType of noType */
     public final Type errType;
 
     /** A value for the unknown type. */
@@ -348,7 +347,7 @@
 
         // create the error symbols
         errSymbol = new ClassSymbol(PUBLIC|STATIC|ACYCLIC, names.any, null, rootPackage);
-        errType = new ErrorType(errSymbol);
+        errType = new ErrorType(errSymbol, Type.noType);
 
         // initialize builtin types
         initType(byteType, "byte", "Byte");
@@ -389,6 +388,9 @@
         scope.enter(booleanType.tsym);
         scope.enter(errType.tsym);
 
+        // Enter symbol for the errSymbol
+        scope.enter(errSymbol);
+
         classes.put(predefClass.fullname, predefClass);
 
         reader = ClassReader.instance(context);
--- a/src/share/classes/com/sun/tools/javac/code/Type.java	Thu Sep 04 14:56:35 2008 -0700
+++ b/src/share/classes/com/sun/tools/javac/code/Type.java	Tue Sep 09 10:28:21 2008 -0700
@@ -1194,21 +1194,24 @@
     public static class ErrorType extends ClassType
             implements javax.lang.model.type.ErrorType {
 
-        public ErrorType() {
+        private Type originalType = null;
+
+        public ErrorType(Type originalType, TypeSymbol tsym) {
             super(noType, List.<Type>nil(), null);
             tag = ERROR;
+            this.tsym = tsym;
+            this.originalType = (originalType == null ? noType : originalType);
         }
 
-        public ErrorType(ClassSymbol c) {
-            this();
-            tsym = c;
+        public ErrorType(ClassSymbol c, Type originalType) {
+            this(originalType, c);
             c.type = this;
             c.kind = ERR;
             c.members_field = new Scope.ErrorScope(c);
         }
 
-        public ErrorType(Name name, TypeSymbol container) {
-            this(new ClassSymbol(PUBLIC|STATIC|ACYCLIC, name, null, container));
+        public ErrorType(Name name, TypeSymbol container, Type originalType) {
+            this(new ClassSymbol(PUBLIC|STATIC|ACYCLIC, name, null, container), originalType);
         }
 
         @Override
@@ -1234,6 +1237,10 @@
             return TypeKind.ERROR;
         }
 
+        public Type getOriginalType() {
+            return originalType;
+        }
+
         public <R, P> R accept(TypeVisitor<R, P> v, P p) {
             return v.visitError(this, p);
         }
--- a/src/share/classes/com/sun/tools/javac/code/Types.java	Thu Sep 04 14:56:35 2008 -0700
+++ b/src/share/classes/com/sun/tools/javac/code/Types.java	Tue Sep 09 10:28:21 2008 -0700
@@ -2187,6 +2187,20 @@
         };
     // </editor-fold>
 
+    // <editor-fold defaultstate="collapsed" desc="createErrorType">
+    public Type createErrorType(Type originalType) {
+        return new ErrorType(originalType, syms.errSymbol);
+    }
+
+    public Type createErrorType(ClassSymbol c, Type originalType) {
+        return new ErrorType(c, originalType);
+    }
+
+    public Type createErrorType(Name name, TypeSymbol container, Type originalType) {
+        return new ErrorType(name, container, originalType);
+    }
+    // </editor-fold>
+
     // <editor-fold defaultstate="collapsed" desc="rank">
     /**
      * The rank of a class is the length of the longest path between
@@ -2604,7 +2618,7 @@
                 if (!bound.isInterface())
                     classCount++;
             if (classCount > 1)
-                return syms.errType;
+                return createErrorType(t);
         }
         return makeCompoundType(bounds);
     }
--- a/src/share/classes/com/sun/tools/javac/comp/Attr.java	Thu Sep 04 14:56:35 2008 -0700
+++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java	Tue Sep 09 10:28:21 2008 -0700
@@ -159,7 +159,7 @@
      *  If check succeeds, store type in tree and return it.
      *  If check fails, store errType in tree and return it.
      *  No checks are performed if the prototype is a method type.
-     *  Its not necessary in this case since we know that kind and type
+     *  It is not necessary in this case since we know that kind and type
      *  are correct.
      *
      *  @param tree     The tree whose kind and type is checked
@@ -176,7 +176,7 @@
                 log.error(tree.pos(), "unexpected.type",
                           kindNames(pkind),
                           kindName(ownkind));
-                owntype = syms.errType;
+                owntype = types.createErrorType(owntype);
             }
         }
         tree.type = owntype;
@@ -524,7 +524,7 @@
             // check that type variable is already visible
             if (t.getUpperBound() == null) {
                 log.error(tree.pos(), "illegal.forward.ref");
-                return syms.errType;
+                return types.createErrorType(t);
             }
         } else {
             t = chk.checkClassType(tree.pos(), t, checkExtensible|!allowGenerics);
@@ -533,12 +533,12 @@
             log.error(tree.pos(), "intf.expected.here");
             // return errType is necessary since otherwise there might
             // be undetected cycles which cause attribution to loop
-            return syms.errType;
+            return types.createErrorType(t);
         } else if (checkExtensible &&
                    classExpected &&
                    (t.tsym.flags() & INTERFACE) != 0) {
             log.error(tree.pos(), "no.intf.expected.here");
-            return syms.errType;
+            return types.createErrorType(t);
         }
         if (checkExtensible &&
             ((t.tsym.flags() & FINAL) != 0)) {
@@ -804,7 +804,7 @@
             Type base = types.asSuper(exprType, syms.iterableType.tsym);
             if (base == null) {
                 log.error(tree.expr.pos(), "foreach.not.applicable.to.type");
-                elemtype = syms.errType;
+                elemtype = types.createErrorType(exprType);
             } else {
                 List<Type> iterableParams = base.allparams();
                 elemtype = iterableParams.isEmpty()
@@ -1219,7 +1219,7 @@
                 if (methName == names._super) {
                     if (site == syms.objectType) {
                         log.error(tree.meth.pos(), "no.superclass", site);
-                        site = syms.errType;
+                        site = types.createErrorType(syms.objectType);
                     } else {
                         site = types.supertype(site);
                     }
@@ -1351,7 +1351,7 @@
         }
 
     public void visitNewClass(JCNewClass tree) {
-        Type owntype = syms.errType;
+        Type owntype = types.createErrorType(tree.type);
 
         // The local environment of a class creation is
         // a new environment nested in the current one.
@@ -1551,7 +1551,7 @@
     }
 
     public void visitNewArray(JCNewArray tree) {
-        Type owntype = syms.errType;
+        Type owntype = types.createErrorType(tree.type);
         Type elemtype;
         if (tree.elemtype != null) {
             elemtype = attribType(tree.elemtype, env);
@@ -1571,7 +1571,7 @@
                     log.error(tree.pos(), "illegal.initializer.for.type",
                               pt);
                 }
-                elemtype = syms.errType;
+                elemtype = types.createErrorType(pt);
             }
         }
         if (tree.elems != null) {
@@ -1631,7 +1631,7 @@
         Symbol operator = tree.operator =
             rs.resolveUnaryOperator(tree.pos(), tree.getTag(), env, argtype);
 
-        Type owntype = syms.errType;
+        Type owntype = types.createErrorType(tree.type);
         if (operator.kind == MTH) {
             owntype = (JCTree.PREINC <= tree.getTag() && tree.getTag() <= JCTree.POSTDEC)
                 ? tree.arg.type
@@ -1667,7 +1667,7 @@
         Symbol operator = tree.operator =
             rs.resolveBinaryOperator(tree.pos(), tree.getTag(), env, left, right);
 
-        Type owntype = syms.errType;
+        Type owntype = types.createErrorType(tree.type);
         if (operator.kind == MTH) {
             owntype = operator.type.getReturnType();
             int opc = chk.checkOperator(tree.lhs.pos(),
@@ -1728,7 +1728,7 @@
     }
 
     public void visitIndexed(JCArrayAccess tree) {
-        Type owntype = syms.errType;
+        Type owntype = types.createErrorType(tree.type);
         Type atype = attribExpr(tree.indexed, env);
         attribExpr(tree.index, env, syms.intType);
         if (types.isArray(atype))
@@ -1849,7 +1849,7 @@
                 elt = ((ArrayType)elt).elemtype;
             if (elt.tag == TYPEVAR) {
                 log.error(tree.pos(), "type.var.cant.be.deref");
-                result = syms.errType;
+                result = types.createErrorType(tree.type);
                 return;
             }
         }
@@ -2009,7 +2009,7 @@
                 }
             case ERROR:
                 // preserve identifier names through errors
-                return new ErrorType(name, site.tsym).tsym;
+                return types.createErrorType(name, site.tsym, site).tsym;
             default:
                 // The qualifier expression is of a primitive type -- only
                 // .class is allowed for these.
@@ -2059,7 +2059,7 @@
                      int pkind,
                      Type pt,
                      boolean useVarargs) {
-            if (pt.isErroneous()) return syms.errType;
+            if (pt.isErroneous()) return types.createErrorType(site);
             Type owntype; // The computed type of this identifier occurrence.
             switch (sym.kind) {
             case TYP:
@@ -2129,7 +2129,7 @@
                     for (List<Type> l = env.info.tvars; l.nonEmpty(); l = l.tail)
                         if (!owntype.contains(l.head)) {
                             log.error(tree.pos(), "undetermined.type", owntype1);
-                            owntype1 = syms.errType;
+                            owntype1 = types.createErrorType(owntype1);
                         }
                     owntype = owntype1;
                 }
@@ -2332,7 +2332,7 @@
                           "internal.error.cant.instantiate",
                           sym, site,
                           Type.toString(pt.getParameterTypes()));
-            owntype = syms.errType;
+            owntype = types.createErrorType(site);
         } else {
             // System.out.println("call   : " + env.tree);
             // System.out.println("method : " + owntype);
@@ -2454,7 +2454,7 @@
      *  before supertype structure is completely known
      */
     public void visitTypeApply(JCTypeApply tree) {
-        Type owntype = syms.errType;
+        Type owntype = types.createErrorType(tree.type);
 
         // Attribute functor part of application and make sure it's a class.
         Type clazztype = chk.checkClassType(tree.clazz.pos(), attribType(tree.clazz, env));
@@ -2498,7 +2498,7 @@
                 } else {
                     log.error(tree.pos(), "type.doesnt.take.params", clazztype.tsym);
                 }
-                owntype = syms.errType;
+                owntype = types.createErrorType(tree.type);
             }
         }
         result = check(tree, owntype, TYP, pkind, pt);
--- a/src/share/classes/com/sun/tools/javac/comp/Check.java	Thu Sep 04 14:56:35 2008 -0700
+++ b/src/share/classes/com/sun/tools/javac/comp/Check.java	Tue Sep 09 10:28:21 2008 -0700
@@ -192,12 +192,12 @@
     Type typeError(DiagnosticPosition pos, Object problem, Type found, Type req) {
         log.error(pos, "prob.found.req",
                   problem, found, req);
-        return syms.errType;
+        return types.createErrorType(found);
     }
 
     Type typeError(DiagnosticPosition pos, String problem, Type found, Type req, Object explanation) {
         log.error(pos, "prob.found.req.1", problem, found, req, explanation);
-        return syms.errType;
+        return types.createErrorType(found);
     }
 
     /** Report an error that wrong type tag was found.
@@ -208,7 +208,7 @@
      */
     Type typeTagError(DiagnosticPosition pos, Object required, Object found) {
         log.error(pos, "type.found.req", found, required);
-        return syms.errType;
+        return types.createErrorType(found instanceof Type ? (Type)found : syms.errType);
     }
 
     /** Report an error that symbol cannot be referenced before super
@@ -348,11 +348,11 @@
             return typeError(pos, diags.fragment("possible.loss.of.precision"), found, req);
         if (found.isSuperBound()) {
             log.error(pos, "assignment.from.super-bound", found);
-            return syms.errType;
+            return types.createErrorType(found);
         }
         if (req.isExtendsBound()) {
             log.error(pos, "assignment.to.extends-bound", req);
-            return syms.errType;
+            return types.createErrorType(found);
         }
         return typeError(pos, diags.fragment("incompatible.types"), found, req);
     }
@@ -378,7 +378,7 @@
                     log.error(pos,
                               "undetermined.type" + (d!=null ? ".1" : ""),
                               t, d);
-                    return syms.errType;
+                    return types.createErrorType(pt);
                 } else {
                     JCDiagnostic d = ex.getDiagnostic();
                     return typeError(pos,
@@ -469,7 +469,7 @@
     Type checkNonVoid(DiagnosticPosition pos, Type t) {
         if (t.tag == VOID) {
             log.error(pos, "void.not.allowed.here");
-            return syms.errType;
+            return types.createErrorType(t);
         } else {
             return t;
         }
@@ -521,7 +521,7 @@
                                 t);
         } else if (!types.isReifiable(t)) {
             log.error(pos, "illegal.generic.type.for.instof");
-            return syms.errType;
+            return types.createErrorType(t);
         } else {
             return t;
         }
@@ -1542,7 +1542,7 @@
             return;
         if (seen.contains(t)) {
             tv = (TypeVar)t;
-            tv.bound = new ErrorType();
+            tv.bound = types.createErrorType(t);
             log.error(pos, "cyclic.inheritance", t);
         } else if (t.tag == TYPEVAR) {
             tv = (TypeVar)t;
@@ -1597,11 +1597,11 @@
     private void noteCyclic(DiagnosticPosition pos, ClassSymbol c) {
         log.error(pos, "cyclic.inheritance", c);
         for (List<Type> l=types.interfaces(c.type); l.nonEmpty(); l=l.tail)
-            l.head = new ErrorType((ClassSymbol)l.head.tsym);
+            l.head = types.createErrorType((ClassSymbol)l.head.tsym, Type.noType);
         Type st = types.supertype(c.type);
         if (st.tag == CLASS)
-            ((ClassType)c.type).supertype_field = new ErrorType((ClassSymbol)st.tsym);
-        c.type = new ErrorType(c);
+            ((ClassType)c.type).supertype_field = types.createErrorType((ClassSymbol)st.tsym, Type.noType);
+        c.type = types.createErrorType(c, c.type);
         c.flags_field |= ACYCLIC;
     }
 
--- a/src/share/classes/com/sun/tools/javac/comp/Enter.java	Thu Sep 04 14:56:35 2008 -0700
+++ b/src/share/classes/com/sun/tools/javac/comp/Enter.java	Tue Sep 09 10:28:21 2008 -0700
@@ -98,6 +98,7 @@
     ClassReader reader;
     Annotate annotate;
     MemberEnter memberEnter;
+    Types types;
     Lint lint;
     JavaFileManager fileManager;
 
@@ -119,6 +120,7 @@
         syms = Symtab.instance(context);
         chk = Check.instance(context);
         memberEnter = MemberEnter.instance(context);
+        types = Types.instance(context);
         annotate = Annotate.instance(context);
         lint = Lint.instance(context);
 
@@ -355,7 +357,7 @@
         // Enter class into `compiled' table and enclosing scope.
         if (chk.compiled.get(c.flatname) != null) {
             duplicateClass(tree.pos(), c);
-            result = new ErrorType(tree.name, (TypeSymbol)owner);
+            result = types.createErrorType(tree.name, (TypeSymbol)owner, Type.noType);
             tree.sym = (ClassSymbol)result.tsym;
             return;
         }
--- a/src/share/classes/com/sun/tools/javac/comp/Infer.java	Thu Sep 04 14:56:35 2008 -0700
+++ b/src/share/classes/com/sun/tools/javac/comp/Infer.java	Tue Sep 09 10:28:21 2008 -0700
@@ -204,7 +204,7 @@
             return true;
         }
 
-    /** Instaniate undetermined type variable to the lub of all its lower bounds.
+    /** Instantiate undetermined type variable to the lub of all its lower bounds.
      *  Throw a NoInstanceException if this not possible.
      */
     void minimizeInst(UndetVar that, Warner warn) throws NoInstanceException {
@@ -216,7 +216,7 @@
             else {
                 that.inst = types.lub(that.lobounds);
             }
-            if (that.inst == null || that.inst == syms.errType)
+            if (that.inst == null || that.inst.tag == ERROR)
                     throw ambiguousNoInstanceException
                         .setMessage("no.unique.minimal.instance.exists",
                                     that.qtype, that.lobounds);
--- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Thu Sep 04 14:56:35 2008 -0700
+++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Tue Sep 09 10:28:21 2008 -0700
@@ -656,7 +656,7 @@
                     return new AmbiguityError(m1, m2);
                 // both abstract, neither overridden; merge throws clause and result type
                 Symbol result;
-                Type result2 = mt2.getReturnType();;
+                Type result2 = mt2.getReturnType();
                 if (mt2.tag == FORALL)
                     result2 = types.subst(result2, ((ForAll)mt2).tvars, ((ForAll)mt1).tvars);
                 if (types.isSubtype(mt1.getReturnType(), result2)) {
@@ -1099,7 +1099,7 @@
             if (sym == syms.errSymbol // preserve the symbol name through errors
                 || ((sym.kind & ERRONEOUS) == 0 // make sure an error symbol is returned
                     && (sym.kind & TYP) != 0))
-                sym = new ErrorType(name, qualified?site.tsym:syms.noSymbol).tsym;
+                sym = types.createErrorType(name, qualified ? site.tsym : syms.noSymbol, sym.type).tsym;
         }
         return sym;
     }
--- a/src/share/classes/javax/lang/model/type/ErrorType.java	Thu Sep 04 14:56:35 2008 -0700
+++ b/src/share/classes/javax/lang/model/type/ErrorType.java	Tue Sep 09 10:28:21 2008 -0700
@@ -25,10 +25,6 @@
 
 package javax.lang.model.type;
 
-
-import javax.lang.model.element.TypeElement;
-
-
 /**
  * Represents a class or interface type that cannot be properly modeled.
  * This may be the result of a processing error,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/api/6557752/T6557752.java	Tue Sep 09 10:28:21 2008 -0700
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+
+/*
+ * @test
+ * @bug     6557752
+ * @summary Test for wrapping the original type in ErrorType.
+ * @library ../lib
+ * @compile T6557752.java
+ * @run main T6557752
+ */
+
+import com.sun.source.tree.AssignmentTree;
+import com.sun.source.tree.CompilationUnitTree;
+import com.sun.source.tree.MethodInvocationTree;
+import com.sun.source.util.JavacTask;
+import com.sun.source.util.TreePath;
+import com.sun.source.util.TreePathScanner;
+import com.sun.source.util.Trees;
+import com.sun.tools.javac.api.JavacTaskImpl;
+import com.sun.tools.javac.util.List;
+import java.io.IOException;
+import java.net.URI;
+import javax.lang.model.type.ErrorType;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.SimpleJavaFileObject;
+import javax.tools.ToolProvider;
+import javax.lang.model.util.Types;
+
+public class T6557752 {
+    static class MyFileObject extends SimpleJavaFileObject {
+        public MyFileObject() {
+            super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
+        }
+        public CharSequence getCharContent(boolean ignoreEncodingErrors) {
+            return "import java.util.*;\n"
+                + "public class Test {\n"
+                + "    void foobar() {\n"
+                + "        Iterator<Number> itr = null;\n"
+                + "        String str = itr.next();\n"
+                + "        FooBar fooBar = FooBar.foobar();\n"
+                + "    }\n"
+                + "}";
+        }
+    }
+    static Trees trees;
+    static JavacTask task = null;
+    public static void main(String[] args) throws IOException {
+        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+        task = (JavacTask) compiler.getTask(null, null, null, null, null, List.of(new MyFileObject()));
+        Iterable<? extends CompilationUnitTree> asts = task.parse();
+        task.analyze();
+        trees = Trees.instance(task);
+        MyVisitor myVisitor = new MyVisitor();
+        for (CompilationUnitTree ast : asts) {
+            myVisitor.compilationUnit = ast;
+            myVisitor.scan(ast, null);
+        }
+
+        if (!myVisitor.foundError) {
+            throw new AssertionError("Expected error not found!");
+        }
+    }
+
+    static class MyVisitor extends TreePathScanner<Void,Void> {
+        public boolean foundError = false;
+        CompilationUnitTree compilationUnit = null;
+        int i = 0;
+        @Override
+        public Void visitMethodInvocation(MethodInvocationTree node, Void ignored) {
+            TreePath path = TreePath.getPath(compilationUnit, node);
+            TypeMirror typeMirror = trees.getTypeMirror(path);
+            if (typeMirror.getKind() == TypeKind.ERROR) {
+              if (i == 0) {
+                String str1 = trees.getOriginalType((ErrorType)typeMirror).toString();
+                if (!str1.equals("java.lang.Number")) {
+                    throw new AssertionError("Trees.getOriginalType() error!");
+                }
+
+                Types types = task.getTypes();
+
+                str1 = types.asElement(trees.getOriginalType((ErrorType)typeMirror)).toString();
+                if (!str1.equals("java.lang.Number")) {
+                    throw new AssertionError("Types.asElement() error!");
+                }
+
+                i++;
+              }
+              else if (i == 1) {
+                String str1 = trees.getOriginalType((ErrorType)typeMirror).toString();
+                if (!str1.equals("FooBar")) {
+                    throw new AssertionError("Trees.getOriginalType() error!");
+                }
+
+                Types types = task.getTypes();
+
+                if (types.asElement(trees.getOriginalType((ErrorType)typeMirror)) != null) {
+                    throw new AssertionError("Ttypes.asElement() error!");
+                }
+                foundError = true;
+              }
+            }
+
+
+            return null;
+        }
+
+    }
+}