# HG changeset patch # User lana # Date 1285371788 25200 # Node ID fd2579b80b83bf5d4289426016c7d29174ba5dd9 # Parent 7ad86852c38a5365c0579136608716828648c82d# Parent c5df455918c44281597a9f7307c42f9ef9a47338 Merge diff -r 7ad86852c38a -r fd2579b80b83 make/build.xml --- a/make/build.xml Thu Sep 23 17:33:52 2010 -0700 +++ b/make/build.xml Fri Sep 24 16:43:08 2010 -0700 @@ -275,6 +275,7 @@ failOnError="false" errorProperty="findbugs.all.errors" warningsProperty="findbugs.all.warnings" + jvm="${target.java.home}/bin/java" jvmargs="-Xmx512M"> @@ -621,7 +622,7 @@ @@ -673,6 +674,7 @@ + @@ -812,7 +814,8 @@ executable="${boot.java.home}/bin/javac" srcdir="${make.tools.dir}/CompileProperties" destdir="${build.toolclasses.dir}/" - classpath="${ant.home}/lib/ant.jar"/> + classpath="${ant.core.lib}" + includeantruntime="false"/> @@ -826,7 +829,8 @@ executable="${boot.java.home}/bin/javac" srcdir="${make.tools.dir}/GenStubs" destdir="${build.toolclasses.dir}/" - classpath="${build.bootstrap.dir}/classes:${ant.home}/lib/ant.jar"/> + classpath="${build.bootstrap.dir}/classes:${ant.core.lib}" + includeantruntime="false"/> @@ -935,7 +939,8 @@ - + @@ -955,6 +960,7 @@ failOnError="false" errorProperty="findbugs.@{name}.errors" warningsProperty="findbugs.@{name}.warnings" + jvm="${target.java.home}/bin/java" jvmargs="-Xmx512M" > diff -r 7ad86852c38a -r fd2579b80b83 src/share/bin/launcher.sh-template --- a/src/share/bin/launcher.sh-template Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/bin/launcher.sh-template Fri Sep 24 16:43:08 2010 -0700 @@ -40,8 +40,8 @@ if [ "$LANGTOOLS_USE_BOOTCLASSPATH" != "no" ]; then cp=`unzip -c "$mylib/#PROGRAM#.jar" META-INF/MANIFEST.MF | grep "Class-Path:" | - sed -e 's|Class-Path: *||' -e 's|\([a-z]*\.jar\) *|'"$mylib"'/\1:|g'` - bcp="$mylib/#PROGRAM#.jar":$cp + sed -e 's|Class-Path: *||' -e 's|\([a-z]*\.jar\) *|'"$mylib"'/\1#PS#|g'` + bcp="$mylib/#PROGRAM#.jar#PS#$cp" fi # tools currently assumes that assertions are enabled in the launcher diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/source/tree/Tree.java --- a/src/share/classes/com/sun/source/tree/Tree.java Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/source/tree/Tree.java Fri Sep 24 16:43:08 2010 -0700 @@ -94,7 +94,7 @@ CATCH(CatchTree.class), /** - * Used for instances of {@link ClassTree}. + * Used for instances of {@link ClassTree} representing classes. */ CLASS(ClassTree.class), @@ -558,6 +558,21 @@ ERRONEOUS(ErroneousTree.class), /** + * Used for instances of {@link ClassTree} representing interfaces. + */ + INTERFACE(ClassTree.class), + + /** + * Used for instances of {@link ClassTree} representing enums. + */ + ENUM(ClassTree.class), + + /** + * Used for instances of {@link ClassTree} representing annotation types. + */ + ANNOTATION_TYPE(ClassTree.class), + + /** * An implementation-reserved node. This is the not the node * you are looking for. */ diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/source/util/TreeScanner.java --- a/src/share/classes/com/sun/source/util/TreeScanner.java Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/source/util/TreeScanner.java Fri Sep 24 16:43:08 2010 -0700 @@ -141,6 +141,7 @@ r = scanAndReduce(node.getReceiverAnnotations(), p, r); r = scanAndReduce(node.getThrows(), p, r); r = scanAndReduce(node.getBody(), p, r); + r = scanAndReduce(node.getDefaultValue(), p, r); return r; } diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/tools/javac/api/JavacTrees.java --- a/src/share/classes/com/sun/tools/javac/api/JavacTrees.java Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/api/JavacTrees.java Fri Sep 24 16:43:08 2010 -0700 @@ -45,6 +45,7 @@ import com.sun.source.util.SourcePositions; import com.sun.source.util.TreePath; import com.sun.source.util.Trees; +import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.code.Symbol.ClassSymbol; import com.sun.tools.javac.code.Symbol.TypeSymbol; import com.sun.tools.javac.code.Symbol; @@ -189,8 +190,24 @@ } public Element getElement(TreePath path) { - Tree t = path.getLeaf(); - return TreeInfo.symbolFor((JCTree) t); + JCTree tree = (JCTree) path.getLeaf(); + Symbol sym = TreeInfo.symbolFor(tree); + if (sym == null && TreeInfo.isDeclaration(tree)) { + for (TreePath p = path; p != null; p = p.getParentPath()) { + JCTree t = (JCTree) p.getLeaf(); + if (t.getTag() == JCTree.CLASSDEF) { + JCClassDecl ct = (JCClassDecl) t; + if (ct.sym != null) { + if ((ct.sym.flags_field & Flags.UNATTRIBUTED) != 0) { + attr.attribClass(ct.pos(), ct.sym); + sym = TreeInfo.symbolFor(tree); + } + break; + } + } + } + } + return sym; } public TypeMirror getTypeMirror(TreePath path) { @@ -258,6 +275,8 @@ env = enter.getTopLevelEnv((JCCompilationUnit)tree); break; case CLASS: + case INTERFACE: + case ENUM: // System.err.println("CLASS: " + ((JCClassDecl)tree).sym.getSimpleName()); env = enter.getClassEnv(((JCClassDecl)tree).sym); break; diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/tools/javac/code/Attribute.java --- a/src/share/classes/com/sun/tools/javac/code/Attribute.java Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/code/Attribute.java Fri Sep 24 16:43:08 2010 -0700 @@ -295,4 +295,11 @@ void visitEnum(Attribute.Enum e); void visitError(Attribute.Error e); } + + /** A mirror of java.lang.annotation.RetentionPolicy. */ + public static enum RetentionPolicy { + SOURCE, + CLASS, + RUNTIME + } } diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/tools/javac/code/Flags.java --- a/src/share/classes/com/sun/tools/javac/code/Flags.java Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/code/Flags.java Fri Sep 24 16:43:08 2010 -0700 @@ -241,6 +241,12 @@ */ public static final long POLYMORPHIC_SIGNATURE = 1L<<40; + /** + * Flag that marks a special kind of bridge methods (the ones that + * come from restricted supertype bounds) + */ + public static final long OVERRIDE_BRIDGE = 1L<<41; + /** Modifier masks. */ public static final int diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/tools/javac/code/Scope.java --- a/src/share/classes/com/sun/tools/javac/code/Scope.java Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/code/Scope.java Fri Sep 24 16:43:08 2010 -0700 @@ -272,6 +272,12 @@ return false; } + static final Filter noFilter = new Filter() { + public boolean accepts(Symbol s) { + return true; + } + }; + /** Return the entry associated with given name, starting in * this scope and proceeding outwards. If no entry was found, * return the sentinel, which is characterized by having a null in @@ -279,13 +285,20 @@ * for regular entries. */ public Entry lookup(Name name) { + return lookup(name, noFilter); + } + public Entry lookup(Name name, Filter sf) { Entry e = table[name.hashCode() & hashMask]; - while (e.scope != null && e.sym.name != name) + while (e.scope != null && (e.sym.name != name || !sf.accepts(e.sym))) e = e.shadowed; return e; } public Iterable getElements() { + return getElements(noFilter); + } + + public Iterable getElements(final Filter sf) { return new Iterable() { public Iterator iterator() { return new Iterator() { @@ -301,7 +314,9 @@ public Symbol next() { Symbol sym = (currEntry == null ? null : currEntry.sym); - currEntry = currEntry.sibling; + if (currEntry != null) { + currEntry = currEntry.sibling; + } update(); return sym; } @@ -311,9 +326,17 @@ } private void update() { + skipToNextMatchingEntry(); while (currEntry == null && currScope.next != null) { currScope = currScope.next; currEntry = currScope.elems; + skipToNextMatchingEntry(); + } + } + + void skipToNextMatchingEntry() { + while (currEntry != null && !sf.accepts(currEntry.sym)) { + currEntry = currEntry.sibling; } } }; diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/tools/javac/code/Source.java --- a/src/share/classes/com/sun/tools/javac/code/Source.java Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/code/Source.java Fri Sep 24 16:43:08 2010 -0700 @@ -171,11 +171,10 @@ public boolean allowUnderscoresInLiterals() { return compareTo(JDK1_7) >= 0; } - public boolean allowStringsInSwitch() { + public boolean allowExoticIdentifiers() { return compareTo(JDK1_7) >= 0; } - // JSR 292: recognize @PolymorphicSignature on java/dyn names - public boolean allowPolymorphicSignature() { + public boolean allowStringsInSwitch() { return compareTo(JDK1_7) >= 0; } public static SourceVersion toSourceVersion(Source source) { diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/tools/javac/code/Symbol.java --- a/src/share/classes/com/sun/tools/javac/code/Symbol.java Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/code/Symbol.java Fri Sep 24 16:43:08 2010 -0700 @@ -214,6 +214,16 @@ return (flags() & INTERFACE) != 0; } + /** Recognize if this symbol was marked @PolymorphicSignature in the source. */ + public boolean isPolymorphicSignatureGeneric() { + return (flags() & (POLYMORPHIC_SIGNATURE | HYPOTHETICAL)) == POLYMORPHIC_SIGNATURE; + } + + /** Recognize if this symbol was split from a @PolymorphicSignature symbol in the source. */ + public boolean isPolymorphicSignatureInstance() { + return (flags() & (POLYMORPHIC_SIGNATURE | HYPOTHETICAL)) == (POLYMORPHIC_SIGNATURE | HYPOTHETICAL); + } + /** Is this symbol declared (directly or indirectly) local * to a method or variable initializer? * Also includes fields of inner classes which are in @@ -579,6 +589,9 @@ public java.util.List getEnclosedElements() { List list = List.nil(); + if (kind == TYP && type.tag == TYPEVAR) { + return list; + } for (Scope.Entry e = members().elems; e != null; e = e.sibling) { if (e.sym != null && (e.sym.flags() & SYNTHETIC) == 0 && e.sym.owner == this) list = list.prepend(e.sym); @@ -1214,7 +1227,18 @@ * as possible implementations. */ public MethodSymbol implementation(TypeSymbol origin, Types types, boolean checkResult) { - MethodSymbol res = types.implementation(this, origin, types, checkResult); + return implementation(origin, types, checkResult, implementation_filter); + } + // where + private static final Filter implementation_filter = new Filter() { + public boolean accepts(Symbol s) { + return s.kind == Kinds.MTH && + (s.flags() & SYNTHETIC) == 0; + } + }; + + public MethodSymbol implementation(TypeSymbol origin, Types types, boolean checkResult, Filter implFilter) { + MethodSymbol res = types.implementation(this, origin, types, checkResult, implFilter); if (res != null) return res; // if origin is derived from a raw type, we might have missed diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/tools/javac/code/Symtab.java --- a/src/share/classes/com/sun/tools/javac/code/Symtab.java Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/code/Symtab.java Fri Sep 24 16:43:08 2010 -0700 @@ -93,6 +93,10 @@ */ public final ClassSymbol errSymbol; + /** The unknown symbol. + */ + public final ClassSymbol unknownSymbol; + /** A value for the errType, with a originalType of noType */ public final Type errType; @@ -354,6 +358,7 @@ // create the error symbols errSymbol = new ClassSymbol(PUBLIC|STATIC|ACYCLIC, names.any, null, rootPackage); + unknownSymbol = new ClassSymbol(PUBLIC|STATIC|ACYCLIC, names.fromString(""), null, rootPackage); errType = new ErrorType(errSymbol, Type.noType); // initialize builtin types @@ -368,7 +373,7 @@ initType(voidType, "void", "Void"); initType(botType, ""); initType(errType, errSymbol); - initType(unknownType, ""); + initType(unknownType, unknownSymbol); // the builtin class of all arrays arrayClass = new ClassSymbol(PUBLIC|ACYCLIC, names.Array, noSymbol); diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/tools/javac/code/TypeAnnotations.java --- a/src/share/classes/com/sun/tools/javac/code/TypeAnnotations.java Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/code/TypeAnnotations.java Fri Sep 24 16:43:08 2010 -0700 @@ -114,6 +114,8 @@ return p; case CLASS: + case INTERFACE: + case ENUM: p.pos = frame.pos; if (((JCClassDecl)frame).extending == tree) { p.type = TargetType.CLASS_EXTENDS; diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/tools/javac/code/Types.java --- a/src/share/classes/com/sun/tools/javac/code/Types.java Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/code/Types.java Fri Sep 24 16:43:08 2010 -0700 @@ -32,6 +32,7 @@ import com.sun.tools.javac.util.List; import com.sun.tools.javac.jvm.ClassReader; +import com.sun.tools.javac.code.Attribute.RetentionPolicy; import com.sun.tools.javac.comp.Check; import static com.sun.tools.javac.code.Type.*; @@ -914,7 +915,7 @@ return true; if (t.isPrimitive() != s.isPrimitive()) - return allowBoxing && isConvertible(t, s, warn); + return allowBoxing && (isConvertible(t, s, warn) || isConvertible(s, t, warn)); if (warn != warnStack.head) { try { @@ -1973,45 +1974,74 @@ hasSameArgs(t, erasure(s)) || hasSameArgs(erasure(t), s); } - private WeakHashMap>> implCache_check = - new WeakHashMap>>(); - - private WeakHashMap>> implCache_nocheck = - new WeakHashMap>>(); - - public MethodSymbol implementation(MethodSymbol ms, TypeSymbol origin, Types types, boolean checkResult) { - Map>> implCache = checkResult ? - implCache_check : implCache_nocheck; - SoftReference> ref_cache = implCache.get(ms); - Map cache = ref_cache != null ? ref_cache.get() : null; - if (cache == null) { - cache = new HashMap(); - implCache.put(ms, new SoftReference>(cache)); + // + class ImplementationCache { + + private WeakHashMap>> _map = + new WeakHashMap>>(); + + class Entry { + final MethodSymbol cachedImpl; + final Filter implFilter; + final boolean checkResult; + + public Entry(MethodSymbol cachedImpl, + Filter scopeFilter, + boolean checkResult) { + this.cachedImpl = cachedImpl; + this.implFilter = scopeFilter; + this.checkResult = checkResult; + } + + boolean matches(Filter scopeFilter, boolean checkResult) { + return this.implFilter == scopeFilter && + this.checkResult == checkResult; + } } - MethodSymbol impl = cache.get(origin); - if (impl == null) { + + MethodSymbol get(MethodSymbol ms, TypeSymbol origin, boolean checkResult, Filter implFilter) { + SoftReference> ref_cache = _map.get(ms); + Map cache = ref_cache != null ? ref_cache.get() : null; + if (cache == null) { + cache = new HashMap(); + _map.put(ms, new SoftReference>(cache)); + } + Entry e = cache.get(origin); + if (e == null || + !e.matches(implFilter, checkResult)) { + MethodSymbol impl = implementationInternal(ms, origin, Types.this, checkResult, implFilter); + cache.put(origin, new Entry(impl, implFilter, checkResult)); + return impl; + } + else { + return e.cachedImpl; + } + } + + private MethodSymbol implementationInternal(MethodSymbol ms, TypeSymbol origin, Types types, boolean checkResult, Filter implFilter) { for (Type t = origin.type; t.tag == CLASS || t.tag == TYPEVAR; t = types.supertype(t)) { while (t.tag == TYPEVAR) t = t.getUpperBound(); TypeSymbol c = t.tsym; - for (Scope.Entry e = c.members().lookup(ms.name); + for (Scope.Entry e = c.members().lookup(ms.name, implFilter); e.scope != null; e = e.next()) { - if (e.sym.kind == Kinds.MTH) { - MethodSymbol m = (MethodSymbol) e.sym; - if (m.overrides(ms, origin, types, checkResult) && - (m.flags() & SYNTHETIC) == 0) { - impl = m; - cache.put(origin, m); - return impl; - } - } + if (e.sym != null && + e.sym.overrides(ms, origin, types, checkResult)) + return (MethodSymbol)e.sym; } } + return null; } - return impl; } + private ImplementationCache implCache = new ImplementationCache(); + + public MethodSymbol implementation(MethodSymbol ms, TypeSymbol origin, Types types, boolean checkResult, Filter implFilter) { + return implCache.get(ms, origin, checkResult, implFilter); + } + // + /** * Does t have the same arguments as s? It is assumed that both * types are (possibly polymorphic) method types. Monomorphic @@ -3554,4 +3584,24 @@ public Type visitType(Type t, S s) { return t; } } // + + + // + + public RetentionPolicy getRetention(Attribute.Compound a) { + RetentionPolicy vis = RetentionPolicy.CLASS; // the default + Attribute.Compound c = a.type.tsym.attribute(syms.retentionType.tsym); + if (c != null) { + Attribute value = c.member(names.value); + if (value != null && value instanceof Attribute.Enum) { + Name levelName = ((Attribute.Enum)value).value.name; + if (levelName == names.SOURCE) vis = RetentionPolicy.SOURCE; + else if (levelName == names.CLASS) vis = RetentionPolicy.CLASS; + else if (levelName == names.RUNTIME) vis = RetentionPolicy.RUNTIME; + else ;// /* fail soft */ throw new AssertionError(levelName); + } + } + return vis; + } + // } diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/tools/javac/comp/Annotate.java --- a/src/share/classes/com/sun/tools/javac/comp/Annotate.java Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/comp/Annotate.java Fri Sep 24 16:43:08 2010 -0700 @@ -182,6 +182,7 @@ if (!method.type.isErroneous()) buf.append(new Pair ((MethodSymbol)method, value)); + t.type = result; } return new Attribute.Compound(a.type, buf.toList()); } @@ -234,6 +235,7 @@ l.head, env)); } + na.type = expected; return new Attribute. Array(expected, buf.toArray(new Attribute[buf.length()])); } diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/tools/javac/comp/Attr.java --- a/src/share/classes/com/sun/tools/javac/comp/Attr.java Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java Fri Sep 24 16:43:08 2010 -0700 @@ -328,6 +328,12 @@ attribExpr(expr, env); } catch (BreakAttr b) { return b.env; + } catch (AssertionError ae) { + if (ae.getCause() instanceof BreakAttr) { + return ((BreakAttr)(ae.getCause())).env; + } else { + throw ae; + } } finally { breakTree = null; log.useSource(prev); @@ -342,6 +348,12 @@ attribStat(stmt, env); } catch (BreakAttr b) { return b.env; + } catch (AssertionError ae) { + if (ae.getCause() instanceof BreakAttr) { + return ((BreakAttr)(ae.getCause())).env; + } else { + throw ae; + } } finally { breakTree = null; log.useSource(prev); @@ -578,6 +590,8 @@ boolean classExpected, boolean interfaceExpected, boolean checkExtensible) { + if (t.isErroneous()) + return t; if (t.tag == TYPEVAR && !classExpected && !interfaceExpected) { // check that type variable is already visible if (t.getUpperBound() == null) { @@ -595,7 +609,7 @@ } else if (checkExtensible && classExpected && (t.tsym.flags() & INTERFACE) != 0) { - log.error(tree.pos(), "no.intf.expected.here"); + log.error(tree.pos(), "no.intf.expected.here"); return types.createErrorType(t); } if (checkExtensible && @@ -1171,7 +1185,10 @@ } public void visitExec(JCExpressionStatement tree) { - attribExpr(tree.expr, env); + //a fresh environment is required for 292 inference to work properly --- + //see Infer.instantiatePolymorphicSignatureInstance() + Env localEnv = env.dup(tree); + attribExpr(tree.expr, localEnv); result = null; } @@ -1429,23 +1446,19 @@ restype.tsym); } - // as a special case, MethodHandle.invoke(abc) and InvokeDynamic.foo(abc) - // has type , and T can be a primitive type. - if (tree.meth.getTag() == JCTree.SELECT && !typeargtypes.isEmpty()) { - JCFieldAccess mfield = (JCFieldAccess) tree.meth; - if ((mfield.selected.type.tsym != null && - (mfield.selected.type.tsym.flags() & POLYMORPHIC_SIGNATURE) != 0) - || - (mfield.sym != null && - (mfield.sym.flags() & POLYMORPHIC_SIGNATURE) != 0)) { - assert types.isSameType(restype, typeargtypes.head) : mtype; - assert mfield.selected.type == syms.methodHandleType - || mfield.selected.type == syms.invokeDynamicType; - typeargtypesNonRefOK = true; - } + // Special case logic for JSR 292 types. + if (rs.allowTransitionalJSR292 && + tree.meth.getTag() == JCTree.SELECT && + !typeargtypes.isEmpty()) { + JCFieldAccess mfield = (JCFieldAccess) tree.meth; + // MethodHandle.invoke(abc) and InvokeDynamic.foo(abc) + // has type , and T can be a primitive type. + if (mfield.sym != null && + mfield.sym.isPolymorphicSignatureInstance()) + typeargtypesNonRefOK = true; } - if (!typeargtypesNonRefOK) { + if (!(rs.allowTransitionalJSR292 && typeargtypesNonRefOK)) { chk.checkRefTypes(tree.typeargs, typeargtypes); } @@ -2009,7 +2022,10 @@ public void visitTypeCast(JCTypeCast tree) { Type clazztype = attribType(tree.clazz, env); chk.validate(tree.clazz, env, false); - Type exprtype = attribExpr(tree.expr, env, Infer.anyPoly); + //a fresh environment is required for 292 inference to work properly --- + //see Infer.instantiatePolymorphicSignatureInstance() + Env localEnv = env.dup(tree); + Type exprtype = attribExpr(tree.expr, localEnv, Infer.anyPoly); Type owntype = chk.checkCastable(tree.expr.pos(), exprtype, clazztype); if (exprtype.constValue() != null) owntype = cfolder.coerce(exprtype, owntype); @@ -2845,7 +2861,6 @@ if (tree.bounds.tail.nonEmpty()) { log.error(tree.bounds.tail.head.pos(), "type.var.may.not.be.followed.by.other.bounds"); - log.unrecoverableError = true; tree.bounds = List.of(tree.bounds.head); a.bound = bs.head; } @@ -3186,4 +3201,104 @@ super.visitMethodDef(tree); } }; + + // + + /** + * Handle missing types/symbols in an AST. This routine is useful when + * the compiler has encountered some errors (which might have ended up + * terminating attribution abruptly); if the compiler is used in fail-over + * mode (e.g. by an IDE) and the AST contains semantic errors, this routine + * prevents NPE to be progagated during subsequent compilation steps. + */ + public void postAttr(Env env) { + new PostAttrAnalyzer().scan(env.tree); + } + + class PostAttrAnalyzer extends TreeScanner { + + private void initTypeIfNeeded(JCTree that) { + if (that.type == null) { + that.type = syms.unknownType; + } + } + + @Override + public void scan(JCTree tree) { + if (tree == null) return; + if (tree instanceof JCExpression) { + initTypeIfNeeded(tree); + } + super.scan(tree); + } + + @Override + public void visitIdent(JCIdent that) { + if (that.sym == null) { + that.sym = syms.unknownSymbol; + } + } + + @Override + public void visitSelect(JCFieldAccess that) { + if (that.sym == null) { + that.sym = syms.unknownSymbol; + } + super.visitSelect(that); + } + + @Override + public void visitClassDef(JCClassDecl that) { + initTypeIfNeeded(that); + if (that.sym == null) { + that.sym = new ClassSymbol(0, that.name, that.type, syms.noSymbol); + } + super.visitClassDef(that); + } + + @Override + public void visitMethodDef(JCMethodDecl that) { + initTypeIfNeeded(that); + if (that.sym == null) { + that.sym = new MethodSymbol(0, that.name, that.type, syms.noSymbol); + } + super.visitMethodDef(that); + } + + @Override + public void visitVarDef(JCVariableDecl that) { + initTypeIfNeeded(that); + if (that.sym == null) { + that.sym = new VarSymbol(0, that.name, that.type, syms.noSymbol); + that.sym.adr = 0; + } + super.visitVarDef(that); + } + + @Override + public void visitNewClass(JCNewClass that) { + if (that.constructor == null) { + that.constructor = new MethodSymbol(0, names.init, syms.unknownType, syms.noSymbol); + } + if (that.constructorType == null) { + that.constructorType = syms.unknownType; + } + super.visitNewClass(that); + } + + @Override + public void visitBinary(JCBinary that) { + if (that.operator == null) + that.operator = new OperatorSymbol(names.empty, syms.unknownType, -1, syms.noSymbol); + super.visitBinary(that); + } + + @Override + public void visitUnary(JCUnary that) { + if (that.operator == null) + that.operator = new OperatorSymbol(names.empty, syms.unknownType, -1, syms.noSymbol); + super.visitUnary(that); + } + } + // } diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/tools/javac/comp/Enter.java --- a/src/share/classes/com/sun/tools/javac/comp/Enter.java Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/comp/Enter.java Fri Sep 24 16:43:08 2010 -0700 @@ -38,6 +38,7 @@ import com.sun.tools.javac.code.Type.*; import com.sun.tools.javac.code.Symbol.*; +import com.sun.tools.javac.main.RecognizedOptions.PkgInfo; import com.sun.tools.javac.tree.JCTree.*; import static com.sun.tools.javac.code.Flags.*; @@ -102,6 +103,7 @@ Lint lint; Names names; JavaFileManager fileManager; + PkgInfo pkginfoOpt; private final Todo todo; @@ -132,6 +134,9 @@ predefClassDef.sym = syms.predefClass; todo = Todo.instance(context); fileManager = context.get(JavaFileManager.class); + + Options options = Options.instance(context); + pkginfoOpt = PkgInfo.get(options); } /** A hashtable mapping classes and packages to the environments current @@ -278,7 +283,7 @@ JavaFileObject.Kind.SOURCE); if (tree.pid != null) { tree.packge = reader.enterPackage(TreeInfo.fullName(tree.pid)); - if (tree.packageAnnotations.nonEmpty()) { + if (tree.packageAnnotations.nonEmpty() || pkginfoOpt == PkgInfo.ALWAYS) { if (isPkgInfo) { addEnv = true; } else { diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/tools/javac/comp/Flow.java --- a/src/share/classes/com/sun/tools/javac/comp/Flow.java Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/comp/Flow.java Fri Sep 24 16:43:08 2010 -0700 @@ -408,7 +408,9 @@ tree = TreeInfo.skipParens(tree); if (tree.getTag() == JCTree.IDENT || tree.getTag() == JCTree.SELECT) { Symbol sym = TreeInfo.symbol(tree); - letInit(tree.pos(), (VarSymbol)sym); + if (sym.kind == VAR) { + letInit(tree.pos(), (VarSymbol)sym); + } } } @@ -481,12 +483,13 @@ /** Split (duplicate) inits/uninits into WhenTrue/WhenFalse sets */ - void split() { + void split(boolean setToNull) { initsWhenFalse = inits.dup(); uninitsWhenFalse = uninits.dup(); initsWhenTrue = inits; uninitsWhenTrue = uninits; - inits = uninits = null; + if (setToNull) + inits = uninits = null; } /** Merge (intersect) inits/uninits from WhenTrue/WhenFalse sets. @@ -568,9 +571,11 @@ uninitsWhenTrue = uninits; } else { scan(tree); - if (inits != null) split(); + if (inits != null) + split(tree.type != syms.unknownType); } - inits = uninits = null; + if (tree.type != syms.unknownType) + inits = uninits = null; } /* ------------ Visitor methods for various sorts of trees -------------*/ @@ -1007,7 +1012,7 @@ List.of(resource.type); for (Type sup : closeableSupertypes) { if (types.asSuper(sup, syms.autoCloseableType.tsym) != null) { - Symbol closeMethod = rs.resolveInternalMethod(tree, + Symbol closeMethod = rs.resolveQualifiedMethod(tree, attrEnv, sup, names.close, @@ -1050,20 +1055,22 @@ List rethrownTypes = chk.diff(thrownInTry, caughtInTry); for (JCExpression ct : subClauses) { Type exc = ct.type; - ctypes = ctypes.append(exc); - if (types.isSameType(exc, syms.objectType)) - continue; - if (chk.subset(exc, caughtInTry)) { - log.error(l.head.pos(), - "except.already.caught", exc); - } else if (!chk.isUnchecked(l.head.pos(), exc) && - exc.tsym != syms.throwableType.tsym && - exc.tsym != syms.exceptionType.tsym && - !chk.intersects(exc, thrownInTry)) { - log.error(l.head.pos(), - "except.never.thrown.in.try", exc); + if (exc != syms.unknownType) { + ctypes = ctypes.append(exc); + if (types.isSameType(exc, syms.objectType)) + continue; + if (chk.subset(exc, caughtInTry)) { + log.error(l.head.pos(), + "except.already.caught", exc); + } else if (!chk.isUnchecked(l.head.pos(), exc) && + exc.tsym != syms.throwableType.tsym && + exc.tsym != syms.exceptionType.tsym && + !chk.intersects(exc, thrownInTry)) { + log.error(l.head.pos(), + "except.never.thrown.in.try", exc); + } + caughtInTry = chk.incl(exc, caughtInTry); } - caughtInTry = chk.incl(exc, caughtInTry); } inits = initsTry.dup(); uninits = uninitsTry.dup(); diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/tools/javac/comp/Infer.java --- a/src/share/classes/com/sun/tools/javac/comp/Infer.java Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/comp/Infer.java Fri Sep 24 16:43:08 2010 -0700 @@ -25,6 +25,8 @@ package com.sun.tools.javac.comp; +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.JCTree.JCTypeCast; import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.List; import com.sun.tools.javac.code.*; @@ -543,4 +545,56 @@ args.head, bounds); } } + + /** + * Compute a synthetic method type corresponding to the requested polymorphic + * method signature. If no explicit return type is supplied, a provisional + * return type is computed (just Object in case of non-transitional 292) + */ + Type instantiatePolymorphicSignatureInstance(Env env, Type site, + Name name, + MethodSymbol spMethod, // sig. poly. method or null if none + List argtypes, + List typeargtypes) { + final Type restype; + if (rs.allowTransitionalJSR292 && typeargtypes.nonEmpty()) { + restype = typeargtypes.head; + } else { + //The return type for a polymorphic signature call is computed from + //the enclosing tree E, as follows: if E is a cast, then use the + //target type of the cast expression as a return type; if E is an + //expression statement, the return type is 'void' - otherwise the + //return type is simply 'Object'. + switch (env.outer.tree.getTag()) { + case JCTree.TYPECAST: + restype = ((JCTypeCast)env.outer.tree).clazz.type; break; + case JCTree.EXEC: + restype = syms.voidType; break; + default: + restype = syms.objectType; + } + } + + List paramtypes = Type.map(argtypes, implicitArgType); + List exType = spMethod != null ? + spMethod.getThrownTypes() : + List.of(syms.throwableType); // make it throw all exceptions + + MethodType mtype = new MethodType(paramtypes, + restype, + exType, + syms.methodClass); + return mtype; + } + //where + Mapping implicitArgType = new Mapping ("implicitArgType") { + public Type apply(Type t) { + t = types.erasure(t); + if (t.tag == BOT) + // nulls type as the marker type Null (which has no instances) + // infer as java.lang.Void for now + t = types.boxedClass(syms.voidType).type; + return t; + } + }; } diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/tools/javac/comp/Lower.java --- a/src/share/classes/com/sun/tools/javac/comp/Lower.java Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/comp/Lower.java Fri Sep 24 16:43:08 2010 -0700 @@ -29,6 +29,7 @@ import com.sun.tools.javac.code.*; import com.sun.tools.javac.jvm.*; +import com.sun.tools.javac.main.RecognizedOptions.PkgInfo; import com.sun.tools.javac.tree.*; import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; @@ -82,6 +83,7 @@ private final Name classDollar; private Types types; private boolean debugLower; + private PkgInfo pkginfoOpt; protected Lower(Context context) { context.put(lowerKey, this); @@ -106,6 +108,7 @@ types = Types.instance(context); Options options = Options.instance(context); debugLower = options.get("debuglower") != null; + pkginfoOpt = PkgInfo.get(options); } /** The currently enclosing class. @@ -2161,7 +2164,7 @@ } public void visitTopLevel(JCCompilationUnit tree) { - if (tree.packageAnnotations.nonEmpty()) { + if (needPackageInfoClass(tree)) { Name name = names.package_info; long flags = Flags.ABSTRACT | Flags.INTERFACE; if (target.isPackageInfoSynthetic()) @@ -2183,6 +2186,23 @@ translated.append(packageAnnotationsClass); } } + // where + private boolean needPackageInfoClass(JCCompilationUnit tree) { + switch (pkginfoOpt) { + case ALWAYS: + return true; + case LEGACY: + return tree.packageAnnotations.nonEmpty(); + case NONEMPTY: + for (Attribute.Compound a: tree.packge.attributes_field) { + Attribute.RetentionPolicy p = types.getRetention(a); + if (p != Attribute.RetentionPolicy.SOURCE) + return true; + } + return false; + } + throw new AssertionError(); + } public void visitClassDef(JCClassDecl tree) { ClassSymbol currentClassPrev = currentClass; @@ -2869,8 +2889,17 @@ /** Unbox an object to a primitive value. */ JCExpression unbox(JCExpression tree, Type primitive) { Type unboxedType = types.unboxedType(tree.type); - // note: the "primitive" parameter is not used. There muse be - // a conversion from unboxedType to primitive. + if (unboxedType.tag == NONE) { + unboxedType = primitive; + if (!unboxedType.isPrimitive()) + throw new AssertionError(unboxedType); + make_at(tree.pos()); + tree = make.TypeCast(types.boxedClass(unboxedType).type, tree); + } else { + // There must be a conversion from unboxedType to primitive. + if (!types.isSubtype(unboxedType, primitive)) + throw new AssertionError(tree); + } make_at(tree.pos()); Symbol valueSym = lookupMethod(tree.pos(), unboxedType.tsym.name.append(names.Value), // x.intValue() diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/tools/javac/comp/MemberEnter.java --- a/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java Fri Sep 24 16:43:08 2010 -0700 @@ -769,9 +769,17 @@ && types.isSameType(c.type, syms.deprecatedType)) s.flags_field |= Flags.DEPRECATED; // Internally to java.dyn, a @PolymorphicSignature annotation - // translates to a classfile attribute. - if (!c.type.isErroneous() - && types.isSameType(c.type, syms.polymorphicSignatureType)) { + // acts like a classfile attribute. + if (!c.type.isErroneous() && + types.isSameType(c.type, syms.polymorphicSignatureType)) { + if (!target.hasMethodHandles()) { + // Somebody is compiling JDK7 source code to a JDK6 target. + // Make it a strict warning, since it is unlikely but important. + log.strictWarning(env.tree.pos(), + "wrong.target.for.polymorphic.signature.definition", + target.name); + } + // Pull the flag through for better diagnostics, even on a bad target. s.flags_field |= Flags.POLYMORPHIC_SIGNATURE; } if (!annotated.add(a.type.tsym)) diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/tools/javac/comp/Resolve.java --- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java Fri Sep 24 16:43:08 2010 -0700 @@ -69,9 +69,13 @@ JCDiagnostic.Factory diags; public final boolean boxingEnabled; // = source.allowBoxing(); public final boolean varargsEnabled; // = source.allowVarargs(); - public final boolean allowPolymorphicSignature; + public final boolean allowMethodHandles; + public final boolean allowInvokeDynamic; + public final boolean allowTransitionalJSR292; private final boolean debugResolve; + Scope polymorphicSignatureScope; + public static Resolve instance(Context context) { Resolve instance = context.get(resolveKey); if (instance == null) @@ -107,7 +111,14 @@ varargsEnabled = source.allowVarargs(); Options options = Options.instance(context); debugResolve = options.get("debugresolve") != null; - allowPolymorphicSignature = source.allowPolymorphicSignature() || options.get("invokedynamic") != null; + allowTransitionalJSR292 = options.get("allowTransitionalJSR292") != null; + Target target = Target.instance(context); + allowMethodHandles = allowTransitionalJSR292 || + target.hasMethodHandles(); + allowInvokeDynamic = (allowTransitionalJSR292 || + target.hasInvokedynamic()) && + options.get("invokedynamic") != null; + polymorphicSignatureScope = new Scope(syms.noSymbol); } /** error symbols, which are returned when resolution fails @@ -246,7 +257,8 @@ /* `sym' is accessible only if not overridden by * another symbol which is a member of `site' * (because, if it is overridden, `sym' is not strictly - * speaking a member of `site'.) + * speaking a member of `site'). A polymorphic signature method + * cannot be overridden (e.g. MH.invokeExact(Object[])). */ private boolean notOverriddenIn(Type site, Symbol sym) { if (sym.kind != MTH || sym.isConstructor() || sym.isStatic()) @@ -254,6 +266,7 @@ else { Symbol s2 = ((MethodSymbol)sym).implementation(site.tsym, types, true); return (s2 == null || s2 == sym || + s2.isPolymorphicSignatureGeneric() || !types.isSubSignature(types.memberType(site, s2), types.memberType(site, sym))); } } @@ -303,7 +316,8 @@ boolean useVarargs, Warner warn) throws Infer.InferenceException { - assert ((m.flags() & (POLYMORPHIC_SIGNATURE|HYPOTHETICAL)) != POLYMORPHIC_SIGNATURE); + boolean polymorphicSignature = (m.isPolymorphicSignatureGeneric() && allowMethodHandles) || + isTransitionalDynamicCallSite(site, m); if (useVarargs && (m.flags() & VARARGS) == 0) return null; Type mt = types.memberType(site, m); @@ -311,7 +325,10 @@ // need to inferred. List tvars = env.info.tvars; if (typeargtypes == null) typeargtypes = List.nil(); - if (mt.tag != FORALL && typeargtypes.nonEmpty()) { + if (allowTransitionalJSR292 && polymorphicSignature && typeargtypes.nonEmpty()) { + //transitional 292 call sites might have wrong number of targs + } + else if (mt.tag != FORALL && typeargtypes.nonEmpty()) { // This is not a polymorphic method, but typeargs are supplied // which is fine, see JLS3 15.12.2.1 } else if (mt.tag == FORALL && typeargtypes.nonEmpty()) { @@ -339,7 +356,8 @@ } // find out whether we need to go the slow route via infer - boolean instNeeded = tvars.tail != null/*inlined: tvars.nonEmpty()*/; + boolean instNeeded = tvars.tail != null || /*inlined: tvars.nonEmpty()*/ + polymorphicSignature; for (List l = argtypes; l.tail != null/*inlined: l.nonEmpty()*/ && !instNeeded; l = l.tail) { @@ -347,8 +365,9 @@ } if (instNeeded) - return - infer.instantiateMethod(env, + return polymorphicSignature ? + infer.instantiatePolymorphicSignatureInstance(env, site, m.name, (MethodSymbol)m, argtypes, typeargtypes) : + infer.instantiateMethod(env, tvars, (MethodType)mt, m, @@ -363,6 +382,14 @@ : null; } + boolean isTransitionalDynamicCallSite(Type site, Symbol sym) { + return allowTransitionalJSR292 && // old logic that doesn't use annotations + !sym.isPolymorphicSignatureInstance() && + ((allowMethodHandles && site == syms.methodHandleType && // invokeExact, invokeGeneric, invoke + (sym.name == names.invoke && sym.isPolymorphicSignatureGeneric())) || + (site == syms.invokeDynamicType && allowInvokeDynamic)); // InvokeDynamic.XYZ + } + /** Same but returns null instead throwing a NoInstanceException */ Type instantiate(Env env, @@ -580,14 +607,6 @@ if (sym.kind == ERR) return bestSoFar; if (!sym.isInheritedIn(site.tsym, types)) return bestSoFar; assert sym.kind < AMBIGUOUS; - if ((sym.flags() & POLYMORPHIC_SIGNATURE) != 0 && allowPolymorphicSignature) { - assert(site.tag == CLASS); - // Never match a MethodHandle.invoke directly. - if (useVarargs | allowBoxing | operator) - return bestSoFar; - // Supply an exactly-typed implicit method instead. - sym = findPolymorphicSignatureInstance(env, sym.owner.type, sym.name, (MethodSymbol) sym, argtypes, typeargtypes); - } try { if (rawInstantiate(env, site, sym, argtypes, typeargtypes, allowBoxing, useVarargs, Warner.noWarnings) == null) { @@ -759,13 +778,6 @@ boolean useVarargs, boolean operator) { Symbol bestSoFar = methodNotFound; - if ((site.tsym.flags() & POLYMORPHIC_SIGNATURE) != 0 && - allowPolymorphicSignature && - site.tag == CLASS && - !(useVarargs | allowBoxing | operator)) { - // supply an exactly-typed implicit method in java.dyn.InvokeDynamic - bestSoFar = findPolymorphicSignatureInstance(env, site, name, null, argtypes, typeargtypes); - } return findMethod(env, site, name, @@ -907,90 +919,6 @@ return bestSoFar; } - /** Find or create an implicit method of exactly the given type (after erasure). - * Searches in a side table, not the main scope of the site. - * This emulates the lookup process required by JSR 292 in JVM. - * @param env The current environment. - * @param site The original type from where the selection - * takes place. - * @param name The method's name. - * @param argtypes The method's value arguments. - * @param typeargtypes The method's type arguments - */ - Symbol findPolymorphicSignatureInstance(Env env, - Type site, - Name name, - MethodSymbol spMethod, // sig. poly. method or null if none - List argtypes, - List typeargtypes) { - assert allowPolymorphicSignature; - //assert site == syms.invokeDynamicType || site == syms.methodHandleType : site; - ClassSymbol c = (ClassSymbol) site.tsym; - Scope implicit = c.members().next; - if (implicit == null) { - c.members().next = implicit = new Scope(c); - } - Type restype; - if (typeargtypes.isEmpty()) { - restype = syms.objectType; - } else { - restype = typeargtypes.head; - if (!typeargtypes.tail.isEmpty()) - return methodNotFound; - } - List paramtypes = Type.map(argtypes, implicitArgType); - long flags; - List exType; - if (spMethod != null) { - exType = spMethod.getThrownTypes(); - flags = spMethod.flags() & AccessFlags; - } else { - // make it throw all exceptions - //assert(site == syms.invokeDynamicType); - exType = List.of(syms.throwableType); - flags = PUBLIC | STATIC; - } - MethodType mtype = new MethodType(paramtypes, - restype, - exType, - syms.methodClass); - flags |= ABSTRACT | HYPOTHETICAL | POLYMORPHIC_SIGNATURE; - Symbol m = null; - for (Scope.Entry e = implicit.lookup(name); - e.scope != null; - e = e.next()) { - Symbol sym = e.sym; - assert sym.kind == MTH; - if (types.isSameType(mtype, sym.type) - && (sym.flags() & STATIC) == (flags & STATIC)) { - m = sym; - break; - } - } - if (m == null) { - // create the desired method - m = new MethodSymbol(flags, name, mtype, c); - implicit.enter(m); - } - assert argumentsAcceptable(argtypes, types.memberType(site, m).getParameterTypes(), - false, false, Warner.noWarnings); - assert null != instantiate(env, site, m, argtypes, typeargtypes, false, false, Warner.noWarnings); - return m; - } - //where - Mapping implicitArgType = new Mapping ("implicitArgType") { - public Type apply(Type t) { return implicitArgType(t); } - }; - Type implicitArgType(Type argType) { - argType = types.erasure(argType); - if (argType.tag == BOT) - // nulls type as the marker type Null (which has no instances) - // TO DO: figure out how to access java.lang.Null safely, else throw nice error - //argType = types.boxedClass(syms.botType).type; - argType = types.boxedClass(syms.voidType).type; // REMOVE - return argType; - } - /** Load toplevel or member class with given fully qualified name and * verify that it is accessible. * @param env The current environment. @@ -1369,16 +1297,77 @@ methodResolutionCache.put(steps.head, sym); steps = steps.tail; } - if (sym.kind >= AMBIGUOUS) {//if nothing is found return the 'first' error - MethodResolutionPhase errPhase = - firstErroneousResolutionPhase(); - sym = access(methodResolutionCache.get(errPhase), - pos, site, name, true, argtypes, typeargtypes); - env.info.varArgs = errPhase.isVarargsRequired; + if (sym.kind >= AMBIGUOUS) { + if (site.tsym.isPolymorphicSignatureGeneric() || + isTransitionalDynamicCallSite(site, sym)) { + //polymorphic receiver - synthesize new method symbol + env.info.varArgs = false; + sym = findPolymorphicSignatureInstance(env, + site, name, null, argtypes, typeargtypes); + } + else { + //if nothing is found return the 'first' error + MethodResolutionPhase errPhase = + firstErroneousResolutionPhase(); + sym = access(methodResolutionCache.get(errPhase), + pos, site, name, true, argtypes, typeargtypes); + env.info.varArgs = errPhase.isVarargsRequired; + } + } else if (allowMethodHandles && sym.isPolymorphicSignatureGeneric()) { + //non-instantiated polymorphic signature - synthesize new method symbol + env.info.varArgs = false; + sym = findPolymorphicSignatureInstance(env, + site, name, (MethodSymbol)sym, argtypes, typeargtypes); } return sym; } + /** Find or create an implicit method of exactly the given type (after erasure). + * Searches in a side table, not the main scope of the site. + * This emulates the lookup process required by JSR 292 in JVM. + * @param env Attribution environment + * @param site The original type from where the selection takes place. + * @param name The method's name. + * @param spMethod A template for the implicit method, or null. + * @param argtypes The required argument types. + * @param typeargtypes The required type arguments. + */ + Symbol findPolymorphicSignatureInstance(Env env, Type site, + Name name, + MethodSymbol spMethod, // sig. poly. method or null if none + List argtypes, + List typeargtypes) { + if (typeargtypes.nonEmpty() && (site.tsym.isPolymorphicSignatureGeneric() || + (spMethod != null && spMethod.isPolymorphicSignatureGeneric()))) { + log.warning(env.tree.pos(), "type.parameter.on.polymorphic.signature"); + } + + Type mtype = infer.instantiatePolymorphicSignatureInstance(env, + site, name, spMethod, argtypes, typeargtypes); + long flags = ABSTRACT | HYPOTHETICAL | POLYMORPHIC_SIGNATURE | + (spMethod != null ? + spMethod.flags() & Flags.AccessFlags : + Flags.PUBLIC | Flags.STATIC); + Symbol m = null; + for (Scope.Entry e = polymorphicSignatureScope.lookup(name); + e.scope != null; + e = e.next()) { + Symbol sym = e.sym; + if (types.isSameType(mtype, sym.type) && + (sym.flags() & Flags.STATIC) == (flags & Flags.STATIC) && + types.isSameType(sym.owner.type, site)) { + m = sym; + break; + } + } + if (m == null) { + // create the desired method + m = new MethodSymbol(flags, name, mtype, site.tsym); + polymorphicSignatureScope.enter(m); + } + return m; + } + /** Resolve a qualified method identifier, throw a fatal error if not * found. * @param pos The position to use for error reporting. diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/tools/javac/comp/TransTypes.java --- a/src/share/classes/com/sun/tools/javac/comp/TransTypes.java Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/comp/TransTypes.java Fri Sep 24 16:43:08 2010 -0700 @@ -283,12 +283,13 @@ ListBuffer bridges) { if (sym.kind == MTH && sym.name != names.init && - (sym.flags() & (PRIVATE | SYNTHETIC | STATIC)) == 0 && + (sym.flags() & (PRIVATE | STATIC)) == 0 && + (sym.flags() & (SYNTHETIC | OVERRIDE_BRIDGE)) != SYNTHETIC && sym.isMemberOf(origin, types)) { MethodSymbol meth = (MethodSymbol)sym; MethodSymbol bridge = meth.binaryImplementation(origin, types); - MethodSymbol impl = meth.implementation(origin, types, true); + MethodSymbol impl = meth.implementation(origin, types, true, overrideBridgeFilter); if (bridge == null || bridge == meth || (impl != null && !bridge.owner.isSubClass(impl.owner, types))) { @@ -304,7 +305,7 @@ // reflection design error. addBridge(pos, meth, impl, origin, false, bridges); } - } else if ((bridge.flags() & SYNTHETIC) != 0) { + } else if ((bridge.flags() & (SYNTHETIC | OVERRIDE_BRIDGE)) == SYNTHETIC) { MethodSymbol other = overridden.get(bridge); if (other != null && other != meth) { if (impl == null || !impl.overrides(other, origin, types, true)) { @@ -327,6 +328,11 @@ } } // where + Filter overrideBridgeFilter = new Filter() { + public boolean accepts(Symbol s) { + return (s.flags() & (SYNTHETIC | OVERRIDE_BRIDGE)) != SYNTHETIC; + } + }; /** * @param method The symbol for which a bridge might have to be added * @param impl The implementation of method @@ -754,6 +760,90 @@ return types.erasure(t); } + private boolean boundsRestricted(ClassSymbol c) { + Type st = types.supertype(c.type); + if (st.isParameterized()) { + List actuals = st.allparams(); + List formals = st.tsym.type.allparams(); + while (!actuals.isEmpty() && !formals.isEmpty()) { + Type actual = actuals.head; + Type formal = formals.head; + + if (!types.isSameType(types.erasure(actual), + types.erasure(formal))) + return true; + + actuals = actuals.tail; + formals = formals.tail; + } + } + return false; + } + + private List addOverrideBridgesIfNeeded(DiagnosticPosition pos, + final ClassSymbol c) { + ListBuffer buf = ListBuffer.lb(); + if (c.isInterface() || !boundsRestricted(c)) + return buf.toList(); + Type t = types.supertype(c.type); + Scope s = t.tsym.members(); + if (s.elems != null) { + for (Symbol sym : s.getElements(new NeedsOverridBridgeFilter(c))) { + + MethodSymbol m = (MethodSymbol)sym; + MethodSymbol member = (MethodSymbol)m.asMemberOf(c.type, types); + MethodSymbol impl = m.implementation(c, types, false); + + if ((impl == null || impl.owner != c) && + !types.isSameType(member.erasure(types), m.erasure(types))) { + addOverrideBridges(pos, m, member, c, buf); + } + } + } + return buf.toList(); + } + // where + class NeedsOverridBridgeFilter implements Filter { + + ClassSymbol c; + + NeedsOverridBridgeFilter(ClassSymbol c) { + this.c = c; + } + public boolean accepts(Symbol s) { + return s.kind == MTH && + !s.isConstructor() && + s.isInheritedIn(c, types) && + (s.flags() & FINAL) == 0 && + (s.flags() & (SYNTHETIC | OVERRIDE_BRIDGE)) != SYNTHETIC; + } + } + + private void addOverrideBridges(DiagnosticPosition pos, + MethodSymbol impl, + MethodSymbol member, + ClassSymbol c, + ListBuffer bridges) { + Type implErasure = impl.erasure(types); + long flags = (impl.flags() & AccessFlags) | SYNTHETIC | BRIDGE | OVERRIDE_BRIDGE; + member = new MethodSymbol(flags, member.name, member.type, c); + JCMethodDecl md = make.MethodDef(member, null); + JCExpression receiver = make.Super(types.supertype(c.type).tsym.erasure(types), c); + Type calltype = erasure(impl.type.getReturnType()); + JCExpression call = + make.Apply(null, + make.Select(receiver, impl).setType(calltype), + translateArgs(make.Idents(md.params), + implErasure.getParameterTypes(), null)) + .setType(calltype); + JCStatement stat = (member.getReturnType().tag == VOID) + ? make.Exec(call) + : make.Return(coerce(call, member.erasure(types).getReturnType())); + md.body = make.Block(0, List.of(stat)); + c.members().enter(member); + bridges.append(md); + } + /************************************************************************** * main method *************************************************************************/ @@ -786,6 +876,7 @@ make.at(tree.pos); if (addBridges) { ListBuffer bridges = new ListBuffer(); + bridges.appendList(addOverrideBridgesIfNeeded(tree, c)); if ((tree.sym.flags() & INTERFACE) == 0) addBridges(tree.pos(), tree.sym, bridges); tree.defs = bridges.toList().prependList(tree.defs); diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/tools/javac/jvm/ClassReader.java --- a/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java Fri Sep 24 16:43:08 2010 -0700 @@ -1098,12 +1098,6 @@ } }, - new AttributeReader(names.PolymorphicSignature, V45_3/*S.B.V51*/, CLASS_OR_MEMBER_ATTRIBUTE) { - void read(Symbol sym, int attrLen) { - sym.flags_field |= POLYMORPHIC_SIGNATURE; - } - }, - // The following attributes for a Code attribute are not currently handled // StackMapTable @@ -1289,6 +1283,9 @@ sym.flags_field |= PROPRIETARY; else proxies.append(proxy); + if (majorVersion >= V51.major && proxy.type.tsym == syms.polymorphicSignatureType.tsym) { + sym.flags_field |= POLYMORPHIC_SIGNATURE; + } } annotate.later(new AnnotationCompleter(sym, proxies.toList())); } diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java --- a/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java Fri Sep 24 16:43:08 2010 -0700 @@ -34,6 +34,7 @@ import javax.tools.JavaFileObject; import com.sun.tools.javac.code.*; +import com.sun.tools.javac.code.Attribute.RetentionPolicy; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.code.Type.*; import com.sun.tools.javac.file.BaseFileObject; @@ -651,13 +652,6 @@ endAttr(alenIdx); acount++; } - if ((flags & POLYMORPHIC_SIGNATURE) != 0) { - if (target.majorVersion < 51) - throw new AssertionError("PolymorphicSignature attributes in java/dyn must be written with -target 7 (required major version is 51, current is"+target.majorVersion+")"); - int alenIdx = writeAttr(names.PolymorphicSignature); - endAttr(alenIdx); - acount++; - } return acount; } @@ -692,7 +686,7 @@ boolean hasInvisible = false; if (m.params != null) for (VarSymbol s : m.params) { for (Attribute.Compound a : s.getAnnotationMirrors()) { - switch (getRetention(a.type.tsym)) { + switch (types.getRetention(a)) { case SOURCE: break; case CLASS: hasInvisible = true; break; case RUNTIME: hasVisible = true; break; @@ -708,7 +702,7 @@ for (VarSymbol s : m.params) { ListBuffer buf = new ListBuffer(); for (Attribute.Compound a : s.getAnnotationMirrors()) - if (getRetention(a.type.tsym) == RetentionPolicy.RUNTIME) + if (types.getRetention(a) == RetentionPolicy.RUNTIME) buf.append(a); databuf.appendChar(buf.length()); for (Attribute.Compound a : buf) @@ -723,7 +717,7 @@ for (VarSymbol s : m.params) { ListBuffer buf = new ListBuffer(); for (Attribute.Compound a : s.getAnnotationMirrors()) - if (getRetention(a.type.tsym) == RetentionPolicy.CLASS) + if (types.getRetention(a) == RetentionPolicy.CLASS) buf.append(a); databuf.appendChar(buf.length()); for (Attribute.Compound a : buf) @@ -747,7 +741,7 @@ ListBuffer visibles = new ListBuffer(); ListBuffer invisibles = new ListBuffer(); for (Attribute.Compound a : attrs) { - switch (getRetention(a.type.tsym)) { + switch (types.getRetention(a)) { case SOURCE: break; case CLASS: invisibles.append(a); break; case RUNTIME: visibles.append(a); break; @@ -785,7 +779,7 @@ if (tc.position.type == TargetType.UNKNOWN || !tc.position.emitToClassfile()) continue; - switch (getRetention(tc.type.tsym)) { + switch (types.getRetention(tc)) { case SOURCE: break; case CLASS: invisibles.append(tc); break; case RUNTIME: visibles.append(tc); break; @@ -815,29 +809,6 @@ return attrCount; } - /** A mirror of java.lang.annotation.RetentionPolicy. */ - enum RetentionPolicy { - SOURCE, - CLASS, - RUNTIME - } - - RetentionPolicy getRetention(TypeSymbol annotationType) { - RetentionPolicy vis = RetentionPolicy.CLASS; // the default - Attribute.Compound c = annotationType.attribute(syms.retentionType.tsym); - if (c != null) { - Attribute value = c.member(names.value); - if (value != null && value instanceof Attribute.Enum) { - Name levelName = ((Attribute.Enum)value).value.name; - if (levelName == names.SOURCE) vis = RetentionPolicy.SOURCE; - else if (levelName == names.CLASS) vis = RetentionPolicy.CLASS; - else if (levelName == names.RUNTIME) vis = RetentionPolicy.RUNTIME; - else ;// /* fail soft */ throw new AssertionError(levelName); - } - } - return vis; - } - /** A visitor to write an attribute including its leading * single-character marker. */ diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/tools/javac/jvm/Target.java --- a/src/share/classes/com/sun/tools/javac/jvm/Target.java Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/jvm/Target.java Fri Sep 24 16:43:08 2010 -0700 @@ -259,6 +259,14 @@ return compareTo(JDK1_7) >= 0; } + /** Does the VM support polymorphic method handle invocation? + * Affects the linkage information output to the classfile. + * An alias for {@code hasInvokedynamic}, since all the JSR 292 features appear together. + */ + public boolean hasMethodHandles() { + return hasInvokedynamic(); + } + /** Although we may not have support for class literals, should we * avoid initializing the class that the literal refers to? * See 4468823 diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/tools/javac/main/JavaCompiler.java --- a/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Fri Sep 24 16:43:08 2010 -0700 @@ -59,6 +59,7 @@ import javax.annotation.processing.Processor; import static javax.tools.StandardLocation.CLASS_OUTPUT; +import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag.*; import static com.sun.tools.javac.util.ListBuffer.lb; // TEMP, until we have a more efficient way to save doc comment info @@ -579,10 +580,8 @@ TaskEvent e = new TaskEvent(TaskEvent.Kind.PARSE, filename); taskListener.started(e); } - int initialErrorCount = log.nerrors; Parser parser = parserFactory.newParser(content, keepComments(), genEndPos, lineDebugInfo); tree = parser.parseCompilationUnit(); - log.unrecoverableError |= (log.nerrors > initialErrorCount); if (verbose) { printVerbose("parsing.done", Long.toString(elapsed(msec))); } @@ -608,7 +607,7 @@ * @param filename The name of the file to be parsed. */ @Deprecated - public JCTree.JCCompilationUnit parse(String filename) throws IOException { + public JCTree.JCCompilationUnit parse(String filename) { JavacFileManager fm = (JavacFileManager)fileManager; return parse(fm.getJavaFileObjectsFromStrings(List.of(filename)).iterator().next()); } @@ -778,7 +777,6 @@ public void compile(List sourceFileObjects, List classnames, Iterable processors) - throws IOException // TODO: temp, from JavacProcessingEnvironment { if (processors != null && processors.iterator().hasNext()) explicitAnnotationProcessingRequested = true; @@ -868,14 +866,19 @@ /** * Parses a list of files. */ - public List parseFiles(Iterable fileObjects) throws IOException { + public List parseFiles(Iterable fileObjects) { if (shouldStop(CompileState.PARSE)) return List.nil(); //parse all files ListBuffer trees = lb(); - for (JavaFileObject fileObject : fileObjects) - trees.append(parse(fileObject)); + Set filesSoFar = new HashSet(); + for (JavaFileObject fileObject : fileObjects) { + if (!filesSoFar.contains(fileObject)) { + filesSoFar.add(fileObject); + trees.append(parse(fileObject)); + } + } return trees.toList(); } @@ -916,6 +919,15 @@ } rootClasses = cdefs.toList(); } + + // Ensure the input files have been recorded. Although this is normally + // done by readSource, it may not have been done if the trees were read + // in a prior round of annotation processing, and the trees have been + // cleaned and are being reused. + for (JCCompilationUnit unit : roots) { + inputFiles.add(unit.sourcefile); + } + return roots; } @@ -941,8 +953,7 @@ * @param processors user provided annotation processors to bypass * discovery, {@code null} means that no processors were provided */ - public void initProcessAnnotations(Iterable processors) - throws IOException { + public void initProcessAnnotations(Iterable processors) { // Process annotations if processing is not disabled and there // is at least one Processor available. Options options = Options.instance(context); @@ -960,8 +971,7 @@ keepComments = true; if (taskListener != null) taskListener.started(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING)); - - + log.deferDiagnostics = true; } else { // free resources procEnvImpl.close(); } @@ -969,8 +979,7 @@ } // TODO: called by JavacTaskImpl - public JavaCompiler processAnnotations(List roots) - throws IOException { + public JavaCompiler processAnnotations(List roots) { return processAnnotations(roots, List.nil()); } @@ -979,16 +988,23 @@ * @param roots a list of compilation units * @return an instance of the compiler in which to complete the compilation */ + // Implementation note: when this method is called, log.deferredDiagnostics + // will have been set true by initProcessAnnotations, meaning that any diagnostics + // that are reported will go into the log.deferredDiagnostics queue. + // By the time this method exits, log.deferDiagnostics must be set back to false, + // and all deferredDiagnostics must have been handled: i.e. either reported + // or determined to be transient, and therefore suppressed. public JavaCompiler processAnnotations(List roots, - List classnames) - throws IOException { // TODO: see TEMP note in JavacProcessingEnvironment + List classnames) { if (shouldStop(CompileState.PROCESS)) { // Errors were encountered. - // If log.unrecoverableError is set, the errors were parse errors + // Unless all the errors are resolve errors, the errors were parse errors // or other errors during enter which cannot be fixed by running // any annotation processors. - if (log.unrecoverableError) + if (unrecoverableError()) { + log.reportDeferredDiagnostics(); return this; + } } // ASSERT: processAnnotations and procEnvImpl should have been set up by @@ -1010,6 +1026,7 @@ log.error("proc.no.explicit.annotation.processing.requested", classnames); } + log.reportDeferredDiagnostics(); return this; // continue regular compilation } @@ -1022,6 +1039,7 @@ if (!explicitAnnotationProcessingRequested()) { log.error("proc.no.explicit.annotation.processing.requested", classnames); + log.reportDeferredDiagnostics(); return this; // TODO: Will this halt compilation? } else { boolean errors = false; @@ -1036,7 +1054,6 @@ if (sym.kind == Kinds.PCK) sym.complete(); if (sym.exists()) { - Name name = names.fromString(nameStr); if (sym.kind == Kinds.PCK) pckSymbols = pckSymbols.prepend((PackageSymbol)sym); else @@ -1052,23 +1069,36 @@ continue; } } - if (errors) + if (errors) { + log.reportDeferredDiagnostics(); return this; + } } } try { JavaCompiler c = procEnvImpl.doProcessing(context, roots, classSymbols, pckSymbols); if (c != this) annotationProcessingOccurred = c.annotationProcessingOccurred = true; + // doProcessing will have handled deferred diagnostics + assert c.log.deferDiagnostics == false; + assert c.log.deferredDiagnostics.size() == 0; return c; } finally { procEnvImpl.close(); } } catch (CompletionFailure ex) { log.error("cant.access", ex.sym, ex.getDetailValue()); + log.reportDeferredDiagnostics(); return this; + } + } + private boolean unrecoverableError() { + for (JCDiagnostic d: log.deferredDiagnostics) { + if (d.getKind() == JCDiagnostic.Kind.ERROR && !d.isFlagSet(RESOLVE_ERROR)) + return true; } + return false; } boolean explicitAnnotationProcessingRequested() { @@ -1119,6 +1149,11 @@ env.toplevel.sourcefile); try { attr.attribClass(env.tree.pos(), env.enclClass.sym); + if (errorCount() > 0 && !shouldStop(CompileState.ATTR)) { + //if in fail-over mode, ensure that AST expression nodes + //are correctly initialized (e.g. they have a type/symbol) + attr.postAttr(env); + } compileStates.put(env, CompileState.ATTR); } finally { diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/tools/javac/main/Main.java --- a/src/share/classes/com/sun/tools/javac/main/Main.java Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/main/Main.java Fri Sep 24 16:43:08 2010 -0700 @@ -282,6 +282,13 @@ } } + // phase this out with JSR 292 PFD + if ("no".equals(options.get("allowTransitionalJSR292"))) { + options.put("allowTransitionalJSR292", null); + } else if (target.hasInvokedynamic() && options.get("allowTransitionalJSR292") == null) { + options.put("allowTransitionalJSR292", "allowTransitionalJSR292"); + } + // handle this here so it works even if no other options given String showClass = options.get("showClass"); if (showClass != null) { @@ -467,10 +474,13 @@ ex.printStackTrace(out); } - /** Print a message reporting an fatal error. + /** Print a message reporting a fatal error. */ void feMessage(Throwable ex) { Log.printLines(out, ex.getMessage()); + if (ex.getCause() != null && options.get("dev") != null) { + ex.getCause().printStackTrace(out); + } } /** Print a message reporting an input/output error. diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/tools/javac/main/OptionName.java --- a/src/share/classes/com/sun/tools/javac/main/OptionName.java Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/main/OptionName.java Fri Sep 24 16:43:08 2010 -0700 @@ -80,6 +80,7 @@ XMAXERRS("-Xmaxerrs"), XMAXWARNS("-Xmaxwarns"), XSTDOUT("-Xstdout"), + XPKGINFO("-Xpkginfo:"), XPRINT("-Xprint"), XPRINTROUNDS("-XprintRounds"), XPRINTPROCESSORINFO("-XprintProcessorInfo"), diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/tools/javac/main/RecognizedOptions.java --- a/src/share/classes/com/sun/tools/javac/main/RecognizedOptions.java Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/main/RecognizedOptions.java Fri Sep 24 16:43:08 2010 -0700 @@ -160,6 +160,7 @@ XMAXERRS, XMAXWARNS, XSTDOUT, + XPKGINFO, XPRINT, XPRINTROUNDS, XPRINTPROCESSORINFO, @@ -217,6 +218,7 @@ XMAXERRS, XMAXWARNS, // XSTDOUT, + XPKGINFO, XPRINT, XPRINTROUNDS, XPRINTPROCESSORINFO, @@ -532,6 +534,9 @@ new XOption(XPREFER, "opt.prefer", Option.ChoiceKind.ONEOF, "source", "newer"), + new XOption(XPKGINFO, "opt.pkginfo", + Option.ChoiceKind.ONEOF, "always", "legacy", "nonempty"), + /* -O is a no-op, accepted for backward compatibility. */ new HiddenOption(O), @@ -598,6 +603,16 @@ }; } + public enum PkgInfo { + ALWAYS, LEGACY, NONEMPTY; + public static PkgInfo get(Options options) { + String v = options.get(XPKGINFO); + return (v == null + ? PkgInfo.LEGACY + : PkgInfo.valueOf(v.toUpperCase())); + } + } + private static Map getXLintChoices() { Map choices = new LinkedHashMap(); choices.put("all", false); diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/tools/javac/model/JavacTypes.java --- a/src/share/classes/com/sun/tools/javac/model/JavacTypes.java Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/model/JavacTypes.java Fri Sep 24 16:43:08 2010 -0700 @@ -103,7 +103,7 @@ public boolean contains(TypeMirror t1, TypeMirror t2) { validateTypeNotIn(t1, EXEC_OR_PKG); validateTypeNotIn(t2, EXEC_OR_PKG); - return ((Type) t1).contains((Type) t2); + return types.containsType((Type) t1, (Type) t2); } public boolean isSubsignature(ExecutableType m1, ExecutableType m2) { diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/tools/javac/parser/JavacParser.java --- a/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Fri Sep 24 16:43:08 2010 -0700 @@ -2781,7 +2781,7 @@ List classOrInterfaceBodyDeclaration(Name className, boolean isInterface) { if (S.token() == SEMI) { S.nextToken(); - return List.of(F.at(Position.NOPOS).Block(0, List.nil())); + return List.nil(); } else { String dc = S.docComment(); int pos = S.pos(); diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/tools/javac/parser/Scanner.java --- a/src/share/classes/com/sun/tools/javac/parser/Scanner.java Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/parser/Scanner.java Fri Sep 24 16:43:08 2010 -0700 @@ -108,6 +108,10 @@ */ private boolean allowUnderscoresInLiterals; + /** Allow exotic identifiers. + */ + private boolean allowExoticIdentifiers; + /** The source language setting. */ private Source source; @@ -181,6 +185,7 @@ allowBinaryLiterals = source.allowBinaryLiterals(); allowHexFloats = source.allowHexFloats(); allowUnderscoresInLiterals = source.allowBinaryLiterals(); + allowExoticIdentifiers = source.allowExoticIdentifiers(); // for invokedynamic } private static final boolean hexFloatsWork = hexFloatsWork(); @@ -1010,6 +1015,10 @@ case '#': scanChar(); if (ch == '\"') { + if (!allowExoticIdentifiers) { + lexError("unsupported.exotic.id", source.name); + allowExoticIdentifiers = true; + } scanChar(); if (ch == '\"') lexError(pos, "empty.bytecode.ident"); diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/tools/javac/processing/JavacFiler.java --- a/src/share/classes/com/sun/tools/javac/processing/JavacFiler.java Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/processing/JavacFiler.java Fri Sep 24 16:43:08 2010 -0700 @@ -34,6 +34,7 @@ import java.util.*; import java.io.Closeable; +import java.io.FileNotFoundException; import java.io.InputStream; import java.io.OutputStream; import java.io.FilterOutputStream; @@ -450,10 +451,15 @@ // TODO: Only support reading resources in selected output // locations? Only allow reading of non-source, non-class // files from the supported input locations? - FileObject fileObject = fileManager.getFileForOutput(location, - pkg.toString(), - relativeName.toString(), - null); + FileObject fileObject = fileManager.getFileForInput(location, + pkg.toString(), + relativeName.toString()); + if (fileObject == null) { + String name = (pkg.length() == 0) + ? relativeName.toString() : (pkg + "/" + relativeName); + throw new FileNotFoundException(name); + } + // If the path was already opened for writing, throw an exception. checkFileReopening(fileObject, false); return new FilerInputFileObject(fileObject); diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java --- a/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Fri Sep 24 16:43:08 2010 -0700 @@ -67,6 +67,8 @@ import com.sun.tools.javac.util.Abort; import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.Convert; +import com.sun.tools.javac.util.FatalError; +import com.sun.tools.javac.util.JCDiagnostic; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.Log; import com.sun.tools.javac.util.JavacMessages; @@ -75,6 +77,7 @@ import com.sun.tools.javac.util.Options; import static javax.tools.StandardLocation.*; +import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag.*; /** * Objects of this class hold and manage the state needed to support @@ -95,6 +98,7 @@ private final boolean procOnly; private final boolean fatalErrors; private final boolean werror; + private final boolean showResolveErrors; private boolean foundTypeProcessors; private final JavacFiler filer; @@ -131,6 +135,10 @@ */ Log log; + /** Diagnostic factory. + */ + JCDiagnostic.Factory diags; + /** * Source level of the compile. */ @@ -146,10 +154,11 @@ private Context context; public JavacProcessingEnvironment(Context context, Iterable processors) { - options = Options.instance(context); this.context = context; log = Log.instance(context); source = Source.instance(context); + diags = JCDiagnostic.Factory.instance(context); + options = Options.instance(context); printProcessorInfo = options.get("-XprintProcessorInfo") != null; printRounds = options.get("-XprintRounds") != null; verbose = options.get("-verbose") != null; @@ -157,6 +166,7 @@ procOnly = options.get("-proc:only") != null || options.get("-Xprint") != null; fatalErrors = options.get("fatalEnterError") != null; + showResolveErrors = options.get("showResolveErrors") != null; werror = options.get("-Werror") != null; platformAnnotations = initPlatformAnnotations(); foundTypeProcessors = false; @@ -818,6 +828,7 @@ compiler = JavaCompiler.instance(context); log = Log.instance(context); + log.deferDiagnostics = true; // the following is for the benefit of JavacProcessingEnvironment.getContext() JavacProcessingEnvironment.this.context = context; @@ -848,8 +859,7 @@ /** Create a new round. */ private Round(Round prev, - Set newSourceFiles, Map newClassFiles) - throws IOException { + Set newSourceFiles, Map newClassFiles) { this(prev.nextContext(), prev.number+1, prev.compiler.log.nwarnings); this.genClassFiles = prev.genClassFiles; @@ -882,8 +892,7 @@ } /** Create the next round to be used. */ - Round next(Set newSourceFiles, Map newClassFiles) - throws IOException { + Round next(Set newSourceFiles, Map newClassFiles) { try { return new Round(this, newSourceFiles, newClassFiles); } finally { @@ -919,10 +928,24 @@ /** Return whether or not an unrecoverable error has occurred. */ boolean unrecoverableError() { - return log.unrecoverableError - || messager.errorRaised() - || (werror && log.nwarnings > 0) - || (fatalErrors && log.nerrors > 0); + if (messager.errorRaised()) + return true; + + for (JCDiagnostic d: log.deferredDiagnostics) { + switch (d.getKind()) { + case WARNING: + if (werror) + return true; + break; + + case ERROR: + if (fatalErrors || !d.isFlagSet(RESOLVE_ERROR)) + return true; + break; + } + } + + return false; } /** Find the set of annotations present in the set of top level @@ -938,7 +961,7 @@ } /** Enter a set of generated class files. */ - List enterClassFiles(Map classFiles) { + private List enterClassFiles(Map classFiles) { ClassReader reader = ClassReader.instance(context); Names names = Names.instance(context); List list = List.nil(); @@ -965,7 +988,7 @@ } /** Enter a set of syntax trees. */ - void enterTrees(List roots) { + private void enterTrees(List roots) { compiler.enterTrees(roots); } @@ -995,6 +1018,15 @@ } } + void showDiagnostics(boolean showAll) { + Set kinds = EnumSet.allOf(JCDiagnostic.Kind.class); + if (!showAll) { + // suppress errors, which are all presumed to be transient resolve errors + kinds.remove(JCDiagnostic.Kind.ERROR); + } + log.reportDeferredDiagnostics(kinds); + } + /** Update the processing state for the current context. */ private void updateProcessingState() { filer.newRound(context); @@ -1083,8 +1115,7 @@ public JavaCompiler doProcessing(Context context, List roots, List classSymbols, - Iterable pckSymbols) - throws IOException { + Iterable pckSymbols) { TaskListener taskListener = context.get(TaskListener.class); log = Log.instance(context); @@ -1107,6 +1138,8 @@ errorStatus = round.unrecoverableError(); moreToDo = moreToDo(); + round.showDiagnostics(errorStatus || showResolveErrors); + // Set up next round. // Copy mutable collections returned from filer. round = round.next( @@ -1121,6 +1154,7 @@ // run last round round.run(true, errorStatus); + round.showDiagnostics(true); filer.warnIfUnclosedFiles(); warnIfUnmatchedOptions(); @@ -1184,13 +1218,19 @@ /** * Free resources related to annotation processing. */ - public void close() throws IOException { + public void close() { filer.close(); if (discoveredProcs != null) // Make calling close idempotent discoveredProcs.close(); discoveredProcs = null; - if (processorClassLoader != null && processorClassLoader instanceof Closeable) - ((Closeable) processorClassLoader).close(); + if (processorClassLoader != null && processorClassLoader instanceof Closeable) { + try { + ((Closeable) processorClassLoader).close(); + } catch (IOException e) { + JCDiagnostic msg = diags.fragment("fatal.err.cant.close.loader"); + throw new FatalError(msg, e); + } + } } private List getTopLevelClasses(List units) { diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/tools/javac/resources/compiler.properties --- a/src/share/classes/com/sun/tools/javac/resources/compiler.properties Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/resources/compiler.properties Fri Sep 24 16:43:08 2010 -0700 @@ -128,6 +128,11 @@ compiler.err.no.superclass=\ {0} has no superclass +compiler.warn.type.parameter.on.polymorphic.signature=\ + change obsolete notation for MethodHandle invocations from x.invoke(y) to (T)x.invoke(y) +compiler.warn.wrong.target.for.polymorphic.signature.definition=\ + MethodHandle API building requires -target 7 runtimes or better; current is -target {0} + compiler.err.concrete.inheritance.conflict=\ methods {0} from {1} and {2} from {3} are inherited with the same signature @@ -550,6 +555,8 @@ Fatal Error: Unable to find field {0} compiler.misc.fatal.err.cant.locate.ctor=\ Fatal Error: Unable to find constructor for {0} +compiler.misc.fatal.err.cant.close.loader=\ + Fatal Error: Cannot close class loader for annotation processors ##### @@ -1240,6 +1247,10 @@ underscores in literals are not supported in -source {0}\n\ (use -source 7 or higher to enable underscores in literals) +compiler.err.unsupported.exotic.id=\ + exotic identifiers #"___" are not supported in -source {0}\n\ +(use -source 7 or higher to enable exotic identifiers) + compiler.err.automatic.resource.management.not.supported.in.source=\ automatic resource management is not supported in -source {0}\n\ (use -source 7 or higher to enable automatic resource management) diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/tools/javac/resources/javac.properties --- a/src/share/classes/com/sun/tools/javac/resources/javac.properties Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/resources/javac.properties Fri Sep 24 16:43:08 2010 -0700 @@ -74,7 +74,9 @@ javac.opt.A=\ Options to pass to annotation processors javac.opt.implicit=\ - Specify whether or not to generate class files for implicitly referenced files + Specify whether or not to generate class files for implicitly referenced files +javac.opt.pkginfo=\ + Specify handling of package-info files javac.opt.arg.class=\ javac.opt.arg.class.list=\ @@ -189,7 +191,7 @@ javac.msg.usage.nonstandard.footer=\ These options are non-standard and subject to change without notice. - + javac.msg.bug=\ An exception has occurred in the compiler ({0}). \ Please file a bug at the Java Developer Connection (http://java.sun.com/webapps/bugreport) \ diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/tools/javac/resources/legacy.properties --- a/src/share/classes/com/sun/tools/javac/resources/legacy.properties Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/resources/legacy.properties Fri Sep 24 16:43:08 2010 -0700 @@ -565,6 +565,7 @@ sun.tools.jar.resources = tiger legacy sun.util = tiger legacy sun.util.calendar = tiger legacy +sun.util.locale = tiger legacy sun.util.logging.resources = tiger legacy sunw.io = tiger legacy sunw.util = tiger legacy diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/tools/javac/tree/JCTree.java --- a/src/share/classes/com/sun/tools/javac/tree/JCTree.java Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/tree/JCTree.java Fri Sep 24 16:43:08 2010 -0700 @@ -340,6 +340,7 @@ public abstract int getTag(); /** Convert a tree to a pretty-printed string. */ + @Override public String toString() { StringWriter s = new StringWriter(); try { @@ -375,6 +376,7 @@ /** Return a shallow copy of this tree. */ + @Override public Object clone() { try { return super.clone(); @@ -587,7 +589,17 @@ @Override public void accept(Visitor v) { v.visitClassDef(this); } - public Kind getKind() { return Kind.CLASS; } + public Kind getKind() { + if ((mods.flags & Flags.ANNOTATION) != 0) + return Kind.ANNOTATION_TYPE; + else if ((mods.flags & Flags.INTERFACE) != 0) + return Kind.INTERFACE; + else if ((mods.flags & Flags.ENUM) != 0) + return Kind.ENUM; + else + return Kind.CLASS; + } + public JCModifiers getModifiers() { return mods; } public Name getSimpleName() { return name; } public List getTypeParameters() { diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/tools/javac/tree/TreeInfo.java --- a/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java Fri Sep 24 16:43:08 2010 -0700 @@ -501,6 +501,10 @@ if (that.sym == sym) result = that; else super.visitVarDef(that); } + public void visitTypeParameter(JCTypeParameter that) { + if (that.type.tsym == sym) result = that; + else super.visitTypeParameter(that); + } } DeclScanner s = new DeclScanner(); tree.accept(s); @@ -633,6 +637,18 @@ } } + public static boolean isDeclaration(JCTree node) { + node = skipParens(node); + switch (node.getTag()) { + case JCTree.CLASSDEF: + case JCTree.METHODDEF: + case JCTree.VARDEF: + return true; + default: + return false; + } + } + /** If this tree is an identifier or a field, return its symbol, * otherwise return null. */ diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/tools/javac/util/FatalError.java --- a/src/share/classes/com/sun/tools/javac/util/FatalError.java Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/util/FatalError.java Fri Sep 24 16:43:08 2010 -0700 @@ -37,12 +37,6 @@ public class FatalError extends Error { private static final long serialVersionUID = 0; - /** Construct a FatalError with no detail message. - */ - public FatalError() { - super(); - } - /** Construct a FatalError with the specified detail message. * @param d A diagnostic containing the reason for failure. */ @@ -50,6 +44,15 @@ super(d.toString()); } + /** Construct a FatalError with the specified detail message + * and cause. + * @param d A diagnostic containing the reason for failure. + * @param t An exception causing the error + */ + public FatalError(JCDiagnostic d, Throwable t) { + super(d.toString(), t); + } + /** Construct a FatalError with the specified detail message. * @param s An English(!) string describing the failure, typically because * the diagnostic resources are missing. diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/tools/javac/util/Filter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/tools/javac/util/Filter.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2010, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package com.sun.tools.javac.util; + +/** + * Simple filter acting as a boolean predicate. Method accepts return true if + * the supplied element matches against the filter. + */ +public interface Filter { + /** + * Does this element match against the filter? + * @param t element to be checked + * @return true if the element satisfy constraints imposed by filter + */ + boolean accepts(T t); +} diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/tools/javac/util/Log.java --- a/src/share/classes/com/sun/tools/javac/util/Log.java Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/util/Log.java Fri Sep 24 16:43:08 2010 -0700 @@ -27,8 +27,10 @@ import java.io.*; import java.util.Arrays; +import java.util.EnumSet; import java.util.HashSet; import java.util.Map; +import java.util.Queue; import java.util.Set; import javax.tools.DiagnosticListener; import javax.tools.JavaFileObject; @@ -110,6 +112,12 @@ */ private JavacMessages messages; + /** + * Deferred diagnostics + */ + public boolean deferDiagnostics; + public Queue deferredDiagnostics = new ListBuffer(); + /** Construct a log with given I/O redirections. */ @Deprecated @@ -204,12 +212,6 @@ */ public int nwarnings = 0; - /** - * Whether or not an unrecoverable error has been seen. - * Unrecoverable errors prevent subsequent annotation processing. - */ - public boolean unrecoverableError; - /** A set of all errors generated so far. This is used to avoid printing an * error message more than once. For each error, a pair consisting of the * source file name and source code position of the error is added to the set. @@ -347,12 +349,32 @@ nwarnings++; } + /** Report all deferred diagnostics, and clear the deferDiagnostics flag. */ + public void reportDeferredDiagnostics() { + reportDeferredDiagnostics(EnumSet.allOf(JCDiagnostic.Kind.class)); + } + + /** Report selected deferred diagnostics, and clear the deferDiagnostics flag. */ + public void reportDeferredDiagnostics(Set kinds) { + deferDiagnostics = false; + JCDiagnostic d; + while ((d = deferredDiagnostics.poll()) != null) { + if (kinds.contains(d.getKind())) + report(d); + } + } + /** * Common diagnostic handling. * The diagnostic is counted, and depending on the options and how many diagnostics have been * reported so far, the diagnostic may be handed off to writeDiagnostic. */ public void report(JCDiagnostic diagnostic) { + if (deferDiagnostics) { + deferredDiagnostics.add(diagnostic); + return; + } + if (expectDiagKeys != null) expectDiagKeys.remove(diagnostic.getCode()); diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/tools/javac/util/Names.java --- a/src/share/classes/com/sun/tools/javac/util/Names.java Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/util/Names.java Fri Sep 24 16:43:08 2010 -0700 @@ -103,7 +103,6 @@ public final Name RuntimeInvisibleTypeAnnotations; public final Name RuntimeVisibleParameterAnnotations; public final Name RuntimeInvisibleParameterAnnotations; - public final Name PolymorphicSignature; public final Name Value; public final Name EnclosingMethod; public final Name desiredAssertionStatus; @@ -116,6 +115,7 @@ public final Name value; public final Name getMessage; public final Name getClass; + public final Name invoke; //allowTransitionalJSR292 only public final Name TYPE; public final Name TYPE_USE; public final Name TYPE_PARAMETER; @@ -215,7 +215,6 @@ RuntimeInvisibleTypeAnnotations = fromString("RuntimeInvisibleTypeAnnotations"); RuntimeVisibleParameterAnnotations = fromString("RuntimeVisibleParameterAnnotations"); RuntimeInvisibleParameterAnnotations = fromString("RuntimeInvisibleParameterAnnotations"); - PolymorphicSignature = fromString("PolymorphicSignature"); Value = fromString("Value"); EnclosingMethod = fromString("EnclosingMethod"); @@ -230,6 +229,7 @@ value = fromString("value"); getMessage = fromString("getMessage"); getClass = fromString("getClass"); + invoke = fromString("invoke"); //allowTransitionalJSR292 only TYPE = fromString("TYPE"); TYPE_USE = fromString("TYPE_USE"); diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/tools/javap/CodeWriter.java --- a/src/share/classes/com/sun/tools/javap/CodeWriter.java Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/tools/javap/CodeWriter.java Fri Sep 24 16:43:08 2010 -0700 @@ -239,7 +239,10 @@ new ArrayList(); if (options.details.contains(InstructionDetailWriter.Kind.SOURCE)) { sourceWriter.reset(classWriter.getClassFile(), attr); - detailWriters.add(sourceWriter); + if (sourceWriter.hasSource()) + detailWriters.add(sourceWriter); + else + println("(Source code not available)"); } if (options.details.contains(InstructionDetailWriter.Kind.LOCAL_VARS)) { diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/com/sun/tools/javap/SourceWriter.java --- a/src/share/classes/com/sun/tools/javap/SourceWriter.java Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/com/sun/tools/javap/SourceWriter.java Fri Sep 24 16:43:08 2010 -0700 @@ -99,7 +99,10 @@ } } } + } + public boolean hasSource() { + return (sourceLines.length > 0); } private void setLineMap(Code_attribute attr) { diff -r 7ad86852c38a -r fd2579b80b83 src/share/classes/javax/tools/ToolProvider.java --- a/src/share/classes/javax/tools/ToolProvider.java Thu Sep 23 17:33:52 2010 -0700 +++ b/src/share/classes/javax/tools/ToolProvider.java Fri Sep 24 16:43:08 2010 -0700 @@ -26,10 +26,14 @@ package javax.tools; import java.io.File; +import java.lang.ref.Reference; +import java.lang.ref.WeakReference; import java.net.URL; import java.net.URLClassLoader; import java.net.MalformedURLException; +import java.util.HashMap; import java.util.Locale; +import java.util.Map; import java.util.logging.Logger; import java.util.logging.Level; import static java.util.logging.Level.*; @@ -44,8 +48,6 @@ */ public class ToolProvider { - private ToolProvider() {} - private static final String propertyName = "sun.tools.ToolProvider"; private static final String loggerName = "javax.tools"; @@ -87,6 +89,9 @@ return null; } + private static final String defaultJavaCompilerName + = "com.sun.tools.javac.api.JavacTool"; + /** * Gets the Java™ programming language compiler provided * with this platform. @@ -94,13 +99,7 @@ * {@code null} if no compiler is provided */ public static JavaCompiler getSystemJavaCompiler() { - if (Lazy.compilerClass == null) - return trace(WARNING, "Lazy.compilerClass == null"); - try { - return Lazy.compilerClass.newInstance(); - } catch (Throwable e) { - return trace(WARNING, e); - } + return instance().getSystemTool(JavaCompiler.class, defaultJavaCompilerName); } /** @@ -113,63 +112,109 @@ * or {@code null} if no tools are provided */ public static ClassLoader getSystemToolClassLoader() { - if (Lazy.compilerClass == null) - return trace(WARNING, "Lazy.compilerClass == null"); - return Lazy.compilerClass.getClassLoader(); + try { + Class c = + instance().getSystemToolClass(JavaCompiler.class, defaultJavaCompilerName); + return c.getClassLoader(); + } catch (Throwable e) { + return trace(WARNING, e); + } } - /** - * This class will not be initialized until one of the above - * methods are called. This ensures that searching for the - * compiler does not affect platform start up. - */ - static class Lazy { - private static final String defaultJavaCompilerName - = "com.sun.tools.javac.api.JavacTool"; - private static final String[] defaultToolsLocation - = { "lib", "tools.jar" }; - static final Class compilerClass; - static { - Class c = null; + + private static ToolProvider instance; + + private static synchronized ToolProvider instance() { + if (instance == null) + instance = new ToolProvider(); + return instance; + } + + // Cache for tool classes. + // Use weak references to avoid keeping classes around unnecessarily + private Map>> toolClasses = new HashMap>>(); + + // Cache for tool classloader. + // Use a weak reference to avoid keeping it around unnecessarily + private Reference refToolClassLoader = null; + + + private ToolProvider() { } + + private T getSystemTool(Class clazz, String name) { + Class c = getSystemToolClass(clazz, name); + try { + return c.asSubclass(clazz).newInstance(); + } catch (Throwable e) { + trace(WARNING, e); + return null; + } + } + + private Class getSystemToolClass(Class clazz, String name) { + Reference> refClass = toolClasses.get(name); + Class c = (refClass == null ? null : refClass.get()); + if (c == null) { try { - c = findClass().asSubclass(JavaCompiler.class); - } catch (Throwable t) { - trace(WARNING, t); + c = findSystemToolClass(name); + } catch (Throwable e) { + return trace(WARNING, e); } - compilerClass = c; + toolClasses.put(name, new WeakReference>(c)); + } + return c.asSubclass(clazz); + } + + private static final String[] defaultToolsLocation = { "lib", "tools.jar" }; + + private Class findSystemToolClass(String toolClassName) + throws MalformedURLException, ClassNotFoundException + { + // try loading class directly, in case tool is on the bootclasspath + try { + return enableAsserts(Class.forName(toolClassName, false, null)); + } catch (ClassNotFoundException e) { + trace(FINE, e); + + // if tool not on bootclasspath, look in default tools location (tools.jar) + ClassLoader cl = (refToolClassLoader == null ? null : refToolClassLoader.get()); + if (cl == null) { + File file = new File(System.getProperty("java.home")); + if (file.getName().equalsIgnoreCase("jre")) + file = file.getParentFile(); + for (String name : defaultToolsLocation) + file = new File(file, name); + + // if tools not found, no point in trying a URLClassLoader + // so rethrow the original exception. + if (!file.exists()) + throw e; + + URL[] urls = { file.toURI().toURL() }; + trace(FINE, urls[0].toString()); + + cl = URLClassLoader.newInstance(urls); + cl.setPackageAssertionStatus("com.sun.tools.javac", true); + refToolClassLoader = new WeakReference(cl); + } + + return Class.forName(toolClassName, false, cl); } - private static Class findClass() - throws MalformedURLException, ClassNotFoundException - { - try { - return enableAsserts(Class.forName(defaultJavaCompilerName, false, null)); - } catch (ClassNotFoundException e) { - trace(FINE, e); - } - File file = new File(System.getProperty("java.home")); - if (file.getName().equalsIgnoreCase("jre")) - file = file.getParentFile(); - for (String name : defaultToolsLocation) - file = new File(file, name); - URL[] urls = {file.toURI().toURL()}; - trace(FINE, urls[0].toString()); - ClassLoader cl = URLClassLoader.newInstance(urls); - cl.setPackageAssertionStatus("com.sun.tools.javac", true); - return Class.forName(defaultJavaCompilerName, false, cl); + } + + private static Class enableAsserts(Class cls) { + try { + ClassLoader loader = cls.getClassLoader(); + if (loader != null) + loader.setPackageAssertionStatus("com.sun.tools.javac", true); + else + trace(FINE, "loader == null"); + } catch (SecurityException ex) { + trace(FINE, ex); } + return cls; + } - private static Class enableAsserts(Class cls) { - try { - ClassLoader loader = cls.getClassLoader(); - if (loader != null) - loader.setPackageAssertionStatus("com.sun.tools.javac", true); - else - trace(FINE, "loader == null"); - } catch (SecurityException ex) { - trace(FINE, ex); - } - return cls; - } - } + } diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/6979683/TestCast6979683_BAD34.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/6979683/TestCast6979683_BAD34.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2010, 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 6979683 + * @summary Verify that casts can narrow and unbox at the same time + * @author jrose + * + * @compile/fail/ref=TestCast6979683_BAD34.java.errlog -XDrawDiagnostics TestCast6979683_BAD34.java + */ + +public class TestCast6979683_BAD34 { + static boolean zconvBAD1(Number o) { return o; } //BAD + //... + //... + //... + //... + //... +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/6979683/TestCast6979683_BAD34.java.errlog --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/6979683/TestCast6979683_BAD34.java.errlog Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,2 @@ +TestCast6979683_BAD34.java:34:49: compiler.err.prob.found.req: (compiler.misc.incompatible.types), java.lang.Number, boolean +1 error diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/6979683/TestCast6979683_BAD35.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/6979683/TestCast6979683_BAD35.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2010, 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 6979683 + * @summary Verify that casts can narrow and unbox at the same time + * @author jrose + * + * @compile/fail/ref=TestCast6979683_BAD35.java.errlog -XDrawDiagnostics TestCast6979683_BAD35.java + */ + +public class TestCast6979683_BAD35 { + //... + static int iconvBAD1(Number o) { return o; } //BAD: cast needed + //... + //... + //... + //... +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/6979683/TestCast6979683_BAD35.java.errlog --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/6979683/TestCast6979683_BAD35.java.errlog Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,2 @@ +TestCast6979683_BAD35.java:35:45: compiler.err.prob.found.req: (compiler.misc.incompatible.types), java.lang.Number, int +1 error diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/6979683/TestCast6979683_BAD36.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/6979683/TestCast6979683_BAD36.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2010, 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 6979683 + * @summary Verify that casts can narrow and unbox at the same time + * @author jrose + * + * @compile/fail/ref=TestCast6979683_BAD36.java.errlog -XDrawDiagnostics TestCast6979683_BAD36.java + */ + +public class TestCast6979683_BAD36 { + //... + //... + static int iconvBAD2(Comparable o) { return o; } //BAD: cast needed + //... + //... + //... +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/6979683/TestCast6979683_BAD36.java.errlog --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/6979683/TestCast6979683_BAD36.java.errlog Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,2 @@ +TestCast6979683_BAD36.java:36:58: compiler.err.prob.found.req: (compiler.misc.incompatible.types), java.lang.Comparable, int +1 error diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/6979683/TestCast6979683_BAD37.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/6979683/TestCast6979683_BAD37.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2010, 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 6979683 + * @summary Verify that casts can narrow and unbox at the same time + * @author jrose + * + * @compile/fail/ref=TestCast6979683_BAD37.java.errlog -XDrawDiagnostics TestCast6979683_BAD37.java + */ + +public class TestCast6979683_BAD37 { + //... + //... + //... + static int iconvBAD3(Comparable o) { return (int)o; } //BAD: wrong instance + //... + //... +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/6979683/TestCast6979683_BAD37.java.errlog --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/6979683/TestCast6979683_BAD37.java.errlog Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,2 @@ +TestCast6979683_BAD37.java:37:61: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), java.lang.Comparable, int +1 error diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/6979683/TestCast6979683_BAD38.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/6979683/TestCast6979683_BAD38.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2010, 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 6979683 + * @summary Verify that casts can narrow and unbox at the same time + * @author jrose + * + * @compile/fail/ref=TestCast6979683_BAD38.java.errlog -XDrawDiagnostics TestCast6979683_BAD38.java + */ + +public class TestCast6979683_BAD38 { + //... + //... + //... + //... + static float cconvBAD1(Comparable o) { return o; } //BAD + //... +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/6979683/TestCast6979683_BAD38.java.errlog --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/6979683/TestCast6979683_BAD38.java.errlog Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,2 @@ +TestCast6979683_BAD38.java:38:62: compiler.err.prob.found.req: (compiler.misc.incompatible.types), java.lang.Comparable, float +1 error diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/6979683/TestCast6979683_BAD39.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/6979683/TestCast6979683_BAD39.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2010, 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 6979683 + * @summary Verify that casts can narrow and unbox at the same time + * @author jrose + * + * @compile/fail/ref=TestCast6979683_BAD39.java.errlog -XDrawDiagnostics TestCast6979683_BAD39.java + */ + +public class TestCast6979683_BAD39 { + //... + //... + //... + //... + //... + static float cconvBAD2(Number o) { return (char)o; } //BAD +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/6979683/TestCast6979683_BAD39.java.errlog --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/6979683/TestCast6979683_BAD39.java.errlog Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,2 @@ +TestCast6979683_BAD39.java:39:53: compiler.err.prob.found.req: (compiler.misc.inconvertible.types), java.lang.Number, char +1 error diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/6979683/TestCast6979683_GOOD.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/6979683/TestCast6979683_GOOD.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2010, 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 6979683 + * @summary Verify that casts can narrow and unbox at the same time + * @author jrose + * + * @compile TestCast6979683_GOOD.java + * @run main TestCast6979683_GOOD + */ + +public class TestCast6979683_GOOD { + public static void main(String... av) { + bugReportExample(); + for (int x = -1; x <= 2; x++) { + zconvTests(x != 0); + iconvTests(x); + bconvTests((byte)x); + cconvTests((char)x); + } + System.out.println("Successfully ran "+tests+" tests."); + } + + static int tests; + static void assertEquals(Object x, Object y) { + if (!x.equals(y)) { + throw new RuntimeException("assertEquals: "+x+" != "+y); + } + ++tests; + } + + static void bugReportExample() { + {} // example in bug report: + Object x = (Object)1; + int y = (int)x; + {} // end example + } + + static boolean zconv1(Boolean o) { return o; } + static boolean zconv2(Object o) { return (boolean)o; } + static boolean zconv3(Comparable o) { return (boolean)o; } + + static void zconvTests(boolean x) { + assertEquals(x, zconv1(x)); + assertEquals(x, zconv2(x)); + assertEquals(x, zconv3(x)); + } + + static int iconv1(Integer o) { return o; } + static int iconv2(Object o) { return (int)o; } + static int iconv3(java.io.Serializable o) { return (int)o; } + static int iconv4(Number o) { return (int)o; } + static int iconv5(Comparable o) { return (int)o; } + + static void iconvTests(int x) { + assertEquals(x, iconv1(x)); + assertEquals(x, iconv2(x)); + assertEquals(x, iconv3(x)); + assertEquals(x, iconv4(x)); + assertEquals(x, iconv5(x)); + } + + static float bconv1(Byte o) { return o; } // note type "float" + static float bconv2(Object o) { return (byte)o; } + static float bconv3(java.io.Serializable o) { return (byte)o; } + static float bconv4(Number o) { return (byte)o; } + + static void bconvTests(byte x) { + float xf = x; + assertEquals(xf, bconv1(x)); + assertEquals(xf, bconv2(x)); + assertEquals(xf, bconv3(x)); + assertEquals(xf, bconv4(x)); + } + + static float cconv1(Character o) { return o; } // note type "float" + static float cconv2(Object o) { return (char)o; } + static float cconv3(java.io.Serializable o) { return (char)o; } + static float cconv4(Comparable o) { return (char)o; } + + static void cconvTests(char x) { + float xf = x; + assertEquals(xf, cconv1(x)); + assertEquals(xf, cconv2(x)); + assertEquals(xf, cconv3(x)); + assertEquals(xf, cconv4(x)); + } + +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/InterfaceAssert.java --- a/test/tools/javac/InterfaceAssert.java Thu Sep 23 17:33:52 2010 -0700 +++ b/test/tools/javac/InterfaceAssert.java Fri Sep 24 16:43:08 2010 -0700 @@ -23,9 +23,11 @@ /* * @test - * @bug 4399129 + * @bug 4399129 6980724 * @summary Check that assertions compile properly when nested in an interface * @author gafter + * @compile InterfaceAssert.java + * @run main InterfaceAssert */ /* diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/T6341023.java --- a/test/tools/javac/T6341023.java Thu Sep 23 17:33:52 2010 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,125 +0,0 @@ -/* - * Copyright (c) 2006, 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 6341023 - * @summary Tree API: Tree.Kind should have mapping to interface - */ - -import com.sun.source.tree.*; - -public class T6341023 { - public static void main(String... args) { - boolean ok = true; - - for (Tree.Kind k: Tree.Kind.values()) { - //System.err.println(k + " " + k.asInterface()); - Class i = k.asInterface(); - switch (k) { - case POSTFIX_INCREMENT: - case POSTFIX_DECREMENT: - case PREFIX_INCREMENT: - case PREFIX_DECREMENT: - case UNARY_PLUS: - case UNARY_MINUS: - case BITWISE_COMPLEMENT: - case LOGICAL_COMPLEMENT: - ok = ok & verify(k, i, i == UnaryTree.class); - break; - - case MULTIPLY: - case DIVIDE: - case REMAINDER: - case PLUS: - case MINUS: - case LEFT_SHIFT: - case RIGHT_SHIFT: - case UNSIGNED_RIGHT_SHIFT: - case LESS_THAN: - case GREATER_THAN: - case LESS_THAN_EQUAL: - case GREATER_THAN_EQUAL: - case EQUAL_TO: - case NOT_EQUAL_TO: - case AND: - case XOR: - case OR: - case CONDITIONAL_AND: - case CONDITIONAL_OR: - ok = ok & verify(k, i, i == BinaryTree.class); - break; - - case MULTIPLY_ASSIGNMENT: - case DIVIDE_ASSIGNMENT: - case REMAINDER_ASSIGNMENT: - case PLUS_ASSIGNMENT: - case MINUS_ASSIGNMENT: - case LEFT_SHIFT_ASSIGNMENT: - case RIGHT_SHIFT_ASSIGNMENT: - case UNSIGNED_RIGHT_SHIFT_ASSIGNMENT: - case AND_ASSIGNMENT: - case XOR_ASSIGNMENT: - case OR_ASSIGNMENT: - ok = ok & verify(k, i, i == CompoundAssignmentTree.class); - break; - - case INT_LITERAL: - case LONG_LITERAL: - case FLOAT_LITERAL: - case DOUBLE_LITERAL: - case BOOLEAN_LITERAL: - case CHAR_LITERAL: - case STRING_LITERAL: - case NULL_LITERAL: - ok = ok & verify(k, i, i == LiteralTree.class); - break; - - case UNBOUNDED_WILDCARD: - case EXTENDS_WILDCARD: - case SUPER_WILDCARD: - ok = ok & verify(k, i, i == WildcardTree.class); - break; - - case OTHER: - ok = ok & verify(k, i, i == null); - break; - - default: - String ks = k.toString().replace("_", "") + "tree"; - String iName = i.getName(); - String is = iName.substring(iName.lastIndexOf(".") + 1); - ok = ok & verify(k, i, ks.equalsIgnoreCase(is)); - } - } - - if (!ok) - throw new AssertionError("test failed"); - } - - static boolean verify(Tree.Kind k, Class c, boolean b) { - if (!b) - System.err.println("error: " + k + " " + c); - return b; - } -} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/T6458749.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/T6458749.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2010, 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 6458749 + * @summary TypeParameterElement.getEnclosedElements() throws NPE within javac + * @build T6458749 + * @compile -processor T6458749 -proc:only T6458749.java + */ + +import java.util.Set; +import javax.annotation.processing.*; +import javax.lang.model.element.*; +import javax.lang.model.util.ElementFilter; +import javax.lang.model.SourceVersion; + +@SupportedAnnotationTypes("*") +public class T6458749 extends AbstractProcessor { + public boolean process(Set tes, RoundEnvironment renv) { + if (!renv.processingOver()) { + for(TypeElement e : ElementFilter.typesIn(renv.getRootElements())) { + System.out.printf("Element %s:%n", e.toString()); + try { + for (TypeParameterElement tp : e.getTypeParameters()) { + System.out.printf("Type param %s", tp.toString()); + if (! tp.getEnclosedElements().isEmpty()) { + throw new AssertionError("TypeParameterElement.getEnclosedElements() should return empty list"); + } + } + } catch (NullPointerException npe) { + throw new AssertionError("NPE from TypeParameterElement.getEnclosedElements()", npe); + } + } + } + return true; + } + + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/T6458823/MyProcessor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/T6458823/MyProcessor.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,55 @@ + /* + * Copyright (c) 2010, 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.Set; +import javax.annotation.processing.*; +import javax.lang.model.element.*; +import javax.lang.model.util.ElementFilter; +import javax.lang.model.SourceVersion; +import static javax.tools.Diagnostic.Kind.*; + +@SupportedAnnotationTypes("*") +public class MyProcessor extends AbstractProcessor { + private Messager messager; + public void init(ProcessingEnvironment processingEnv) { + this.messager = processingEnv.getMessager(); + } + + public boolean process(Set tes, RoundEnvironment renv) { + if (!renv.processingOver()) { + for(TypeElement e : ElementFilter.typesIn(renv.getRootElements())) { + for (TypeParameterElement tp : e.getTypeParameters()) { + if (tp.getSimpleName().toString().length() > 1) { + messager.printMessage(WARNING, + "Type param names should be of length 1", tp); + } + } + } + } + return true; + } + + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/T6458823/T6458823.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/T6458823/T6458823.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2010, 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 6458823 + * @summary Messager messages on TypeParamterElements to not include position information. + * + * @compile MyProcessor.java T6458823.java + * @run main T6458823 + */ + +import java.io.File; +import java.io.IOException; +import java.io.Writer; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.tools.Diagnostic; +import javax.tools.DiagnosticCollector; +import javax.tools.JavaCompiler; +import javax.tools.JavaCompiler.CompilationTask; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.ToolProvider; + +public class T6458823 { + public static void main(String[] args) throws Exception { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + if (compiler == null) { + throw new RuntimeException("can't get javax.tools.JavaCompiler!"); + } + DiagnosticCollector diagColl = + new DiagnosticCollector(); + StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null); + List options = new ArrayList(); + options.add("-processor"); + options.add("MyProcessor"); + options.add("-proc:only"); + List files = new ArrayList(); + files.add(new File(T6458823.class.getResource("TestClass.java").toURI())); + final CompilationTask task = compiler.getTask(null, fm, diagColl, + options, null, fm.getJavaFileObjectsFromFiles(files)); + task.call(); + int diagCount = 0; + for (Diagnostic diag : diagColl.getDiagnostics()) { + if (diag.getKind() != Diagnostic.Kind.WARNING) { + throw new AssertionError("Only warnings expected"); + } + System.out.println(diag); + if (diag.getPosition() == Diagnostic.NOPOS) { + throw new AssertionError("No position info in message"); + } + if (diag.getSource() == null) { + throw new AssertionError("No source info in message"); + } + diagCount++; + } + if (diagCount != 2) { + throw new AssertionError("unexpected number of warnings: " + + diagCount + ", expected: 2"); + } + } +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/T6458823/TestClass.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/T6458823/TestClass.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2010, 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. + */ + +class TestClass { +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/T6855236.java --- a/test/tools/javac/T6855236.java Thu Sep 23 17:33:52 2010 -0700 +++ b/test/tools/javac/T6855236.java Fri Sep 24 16:43:08 2010 -0700 @@ -71,12 +71,10 @@ @Override public Object visitMethodInvocation(MethodInvocationTree node, Trees p) { - System.out.print("current path: "); + System.out.println("current path: "); for (Tree t : getCurrentPath()) { - System.out.print('/'); - System.out.print(t); - } - System.out.println(); + System.out.println(" " + t.getKind() + ": " + trim(t, 64)); + } System.out.println("parent path: " + getCurrentPath().getParentPath()); System.out.println("method select: " + node.getMethodSelect().toString()); for (ExpressionTree arg : node.getArguments()) { @@ -88,12 +86,20 @@ @Override public Object visitExpressionStatement(ExpressionStatementTree node, Trees p) { ExpressionTree t = node.getExpression(); - System.out.println("expression statement: " + t.toString()); + System.out.println(); + System.out.println("expression statement: " + trim(t, 64)); return super.visitExpressionStatement(node, p); } } + private String trim(Tree t, int len) { + String s = t.toString().trim().replaceAll("\\s+", " "); + if (s.length() > len) + s = s.substring(0, len) + "..."; + return s; + } + } diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/T6900149.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/T6900149.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2010, 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 6900149 + * @summary IllegalStateException when compiling same files and DiagnosticListener is set + */ + +import java.io.*; +import java.util.*; +import javax.tools.*; +import javax.tools.JavaCompiler.CompilationTask; + +public class T6900149 { + public static void main(String[] args) throws IOException { + DiagnosticCollector diag = + new DiagnosticCollector(); + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + StandardJavaFileManager fm = + compiler.getStandardFileManager(null, null, null); + File emptyFile = File.createTempFile("Empty", ".java"); + File[] files = new File[] { emptyFile, emptyFile }; + CompilationTask task = compiler.getTask(null, fm, diag, + null, null, fm.getJavaFileObjects(files)); + if (! task.call()) { + throw new AssertionError("compilation failed"); + } + } +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/T6956462/T6956462.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/T6956462/T6956462.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2010, 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 6956462 + * @summary AssertionError exception throws in the Compiler Tree API in JDK 7. + * + * @build TestClass T6956462 + * @run main T6956462 + */ + +import java.io.*; +import java.net.URISyntaxException; +import java.util.*; +import javax.tools.*; +import javax.tools.JavaCompiler.CompilationTask; +import com.sun.source.tree.*; +import com.sun.source.util.*; + +public class T6956462 { + public static void main(String[] args) throws Exception { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + if (compiler == null) { + throw new RuntimeException("can't get javax.tools.JavaCompiler!"); + } + StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null); + List files = new ArrayList(); + files.add(new File(T6956462.class.getResource("TestClass.java").toURI())); + final CompilationTask task = compiler.getTask(null, fm, null, + null, null, fm.getJavaFileObjectsFromFiles(files)); + JavacTask javacTask = (JavacTask) task; + for (CompilationUnitTree cu : javacTask.parse()) { + cu.accept(new MyVisitor(javacTask), null); + } + } + + private static class MyVisitor extends SimpleTreeVisitor { + private final Trees trees; + private CompilationUnitTree file; + + private MyVisitor(JavacTask javac) { + this.trees = Trees.instance(javac); + } + + @Override + public Tree visitCompilationUnit(CompilationUnitTree file, Void v) { + this.file = file; + for (Tree typeDecl : file.getTypeDecls()) { + typeDecl.accept(this, v); + } + return null; + } + + @Override + public Tree visitImport(ImportTree imp, Void v) { + return null; + } + + @Override + public Tree visitMethodInvocation(MethodInvocationTree invoke, Void v) { + invoke.getMethodSelect().accept(this, v); + return null; + } + + @Override + public Tree visitBlock(BlockTree block, Void v) { + for (StatementTree stat : block.getStatements()) { + stat.accept(this, v); + } + return null; + } + + @Override + public Tree visitClass(ClassTree clazz, Void v) { + for (Tree member : clazz.getMembers()) { + member.accept(this, v); + } + return null; + } + + @Override + public Tree visitIdentifier(IdentifierTree ident, Void v) { + trees.getScope(trees.getPath(file, ident)); + return null; + } + + @Override + public Tree visitMethod(MethodTree method, Void v) { + method.getBody().accept(this, v); + return null; + } + + @Override + public Tree visitMemberSelect(MemberSelectTree select, Void v) { + select.getExpression().accept(this, v); + return null; + } + + @Override + public Tree visitVariable(VariableTree var, Void v) { + var.getInitializer().accept(this, v); + return null; + } + } +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/T6956462/TestClass.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/T6956462/TestClass.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2010, 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.PrintStream; + +abstract class TestClass { + private void test() { + final PrintStream out = System.out; + } +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/T6985181.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/T6985181.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2010, 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 6985181 + * @summary Annotations lost from classfile + */ + +import java.io.*; +import java.util.*; + +public class T6985181 { + public static void main(String... args) throws Exception{ + new T6985181().run(); + } + + public void run() throws Exception { + String code = "@interface Simple { }\ninterface Test<@Simple T> { }"; + + File srcFile = writeFile("Test.java", code); + File classesDir = new File("classes"); + classesDir.mkdirs(); + compile("-d", classesDir.getPath(), srcFile.getPath()); + String out = javap(new File(classesDir, srcFile.getName().replace(".java", ".class"))); + if (!out.contains("RuntimeInvisibleTypeAnnotations")) + throw new Exception("RuntimeInvisibleTypeAnnotations not found"); + } + + void compile(String... args) throws Exception { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + int rc = com.sun.tools.javac.Main.compile(args, pw); + pw.close(); + String out = sw.toString(); + if (out.length() > 0) + System.err.println(out); + if (rc != 0) + throw new Exception("Compilation failed: rc=" + rc); + } + + String javap(File classFile) throws Exception { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + String[] args = { "-v", classFile.getPath() }; + int rc = com.sun.tools.javap.Main.run(args, pw); + pw.close(); + String out = sw.toString(); + if (out.length() > 0) + System.err.println(out); + if (rc != 0) + throw new Exception("javap failed: rc=" + rc); + return out; + } + + File writeFile(String path, String body) throws IOException { + File f = new File(path); + FileWriter out = new FileWriter(f); + try { + out.write(body); + } finally { + out.close(); + } + return f; + } +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/TestPkgInfo.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/TestPkgInfo.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2010, 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 6960424 + * @summary new option -Xpkginfo for better control of when package-info.class is generated + */ + +import java.io.*; +import java.util.*; + +public class TestPkgInfo { + enum OptKind { + NONE(null), + ALWAYS("-Xpkginfo:always"), + NONEMPTY("-Xpkginfo:nonempty"), + LEGACY("-Xpkginfo:legacy"); + OptKind(String opt) { this.opt = opt; } + final String opt; + }; + + public static void main(String... args) throws Exception { + new TestPkgInfo().run(args); + } + + public void run(String... args) throws Exception { + boolean[] booleanValues = { false, true }; + for (OptKind ok: OptKind.values()) { + for (boolean sr: booleanValues) { + for (boolean cr: booleanValues) { + for (boolean rr: booleanValues) { + try { + test(ok, sr, cr, rr); + } catch (Exception e) { + error("Exception: " + e); + } + if (errors > 0) throw new AssertionError(); + } + } + } + } + + if (errors > 0) + throw new Exception(errors + " errors occurred"); + } + + void test(OptKind ok, boolean sr, boolean cr, boolean rr) throws Exception { + count++; + System.err.println("Test " + count + ": ok:" + ok + " sr:" + sr + " cr:" + cr + " rr:" + rr); + + StringBuilder sb = new StringBuilder(); + + // create annotated package statement with all combinations of retention policy + if (sr) sb.append("@SR\n"); + if (cr) sb.append("@CR\n"); + if (rr) sb.append("@RR\n"); + sb.append("package p;\n"); + sb.append("\n"); + + sb.append("import java.lang.annotation.*;\n"); + sb.append("@Retention(RetentionPolicy.SOURCE) @interface SR { }\n"); + sb.append("@Retention(RetentionPolicy.CLASS) @interface CR { }\n"); + sb.append("@Retention(RetentionPolicy.RUNTIME) @interface RR { }\n"); + + // test specific tmp directory + File tmpDir = new File("tmp.test" + count); + File classesDir = new File(tmpDir, "classes"); + classesDir.mkdirs(); + File pkginfo_java = new File(new File(tmpDir, "src"), "package-info.java"); + writeFile(pkginfo_java, sb.toString()); + + // build up list of options and files to be compiled + List opts = new ArrayList(); + List files = new ArrayList(); + + opts.add("-d"); + opts.add(classesDir.getPath()); + if (ok.opt != null) + opts.add(ok.opt); + //opts.add("-verbose"); + files.add(pkginfo_java); + + compile(opts, files); + + File pkginfo_class = new File(new File(classesDir, "p"), "package-info.class"); + boolean exists = pkginfo_class.exists(); + + boolean expected; + switch (ok) { + case ALWAYS: + expected = true; + break; + + case LEGACY: + case NONE: + expected = (sr || cr || rr ); // any annotation + break; + + case NONEMPTY: + expected = (cr || rr ); // any annotation in class file + break; + + default: + throw new IllegalStateException(); + } + + if (exists && !expected) + error("package-info.class found but not expected"); + if (!exists && expected) + error("package-info.class expected but not found"); + } + + /** Compile files with options provided. */ + void compile(List opts, List files) throws Exception { + System.err.println("javac: " + opts + " " + files); + List args = new ArrayList(); + args.addAll(opts); + for (File f: files) + args.add(f.getPath()); + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + int rc = com.sun.tools.javac.Main.compile(args.toArray(new String[args.size()]), pw); + pw.flush(); + if (sw.getBuffer().length() > 0) + System.err.println(sw.toString()); + if (rc != 0) + throw new Exception("compilation failed: rc=" + rc); + } + + /** Write a file with a given body. */ + void writeFile(File f, String body) throws Exception { + if (f.getParentFile() != null) + f.getParentFile().mkdirs(); + Writer out = new FileWriter(f); + try { + out.write(body); + } finally { + out.close(); + } + } + + /** Report an error. */ + void error(String msg) { + System.err.println("Error: " + msg); + errors++; + } + + /** Test case counter. */ + int count; + + /** Number of errors found. */ + int errors; +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/api/T6392782.java --- a/test/tools/javac/api/T6392782.java Thu Sep 23 17:33:52 2010 -0700 +++ b/test/tools/javac/api/T6392782.java Fri Sep 24 16:43:08 2010 -0700 @@ -47,12 +47,12 @@ check(scanner, 6, scanner.scan(trees, null)); CountNodes nodeCounter = new CountNodes(); - // 383 nodes with the regular parser; 384 nodes with EndPosParser - // We automatically swith to EndPosParser when calling JavacTask.parse() - check(nodeCounter, 384, nodeCounter.scan(trees, null)); + // 359 nodes with the regular parser; 360 nodes with EndPosParser + // We automatically switch to EndPosParser when calling JavacTask.parse() + check(nodeCounter, 360, nodeCounter.scan(trees, null)); CountIdentifiers idCounter = new CountIdentifiers(); - check(idCounter, 106, idCounter.scan(trees, null)); + check(idCounter, 107, idCounter.scan(trees, null)); } private static void check(TreeScanner scanner, int expect, int found) { @@ -73,10 +73,11 @@ } } - // example from TreeScanner javadoc static class CountNodes extends TreeScanner { @Override public Integer scan(Tree node, Void p) { + if (node == null) + return 0; Integer n = super.scan(node, p); return (n == null ? 0 : n) + 1; } diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/api/TestContainTypes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/api/TestContainTypes.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2010, 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 6981185 + * @summary com.sun.tools.model.JavacTypes.contains() calls Type.contains instead of Types.containsType + * @run main TestContainTypes + */ + +import java.net.URI; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.RoundEnvironment; +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.type.DeclaredType; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.SimpleJavaFileObject; +import javax.tools.ToolProvider; + +import com.sun.source.util.JavacTask; +import javax.annotation.processing.SupportedSourceVersion; +import javax.lang.model.SourceVersion; + +public class TestContainTypes { + + enum ClassType { + OBJECT("Object"), + NUMBER("Number"), + INTEGER("Integer"), + STRING("String"); + + String classStub; + + ClassType(String classStub) { + this.classStub = classStub; + } + + boolean subtypeOf(ClassType that) { + switch (that) { + case OBJECT: return true; + case NUMBER: return this == NUMBER || this == INTEGER; + case INTEGER: return this == INTEGER; + case STRING: return this == STRING; + default: throw new AssertionError("Bad type kind in subtyping test"); + } + } + } + + enum ParameterType { + INVARIANT("List<#1>"), + COVARIANT("List"), + CONTRAVARIANT("List"), + BIVARIANT("List"); + + String paramTypeStub; + + ParameterType(String paramTypeStub) { + this.paramTypeStub = paramTypeStub; + } + + String instantiate(ClassType ct) { + return paramTypeStub.replace("#1", ct.classStub); + } + + static boolean contains(ParameterType pt1, ClassType ct1, + ParameterType pt2, ClassType ct2) { + switch (pt1) { + case INVARIANT: return (pt2 == INVARIANT && ct1 == ct2) || + (pt2 == CONTRAVARIANT && ct1 == ct2 && ct1 == ClassType.OBJECT); + case COVARIANT: return ((pt2 == INVARIANT || pt2 == COVARIANT) && + ct2.subtypeOf(ct1)) || + (ct1 == ClassType.OBJECT); + case CONTRAVARIANT: return (pt2 == INVARIANT || pt2 == CONTRAVARIANT) && + ct1.subtypeOf(ct2); + case BIVARIANT: return true; + default: throw new AssertionError("Bad type kind in containment test"); + } + } + } + + static class JavaSource extends SimpleJavaFileObject { + + final static String sourceStub = + "import java.util.List;\n" + + "@interface ToCheck {}\n" + + "class Test {\n" + + " @ToCheck void test(#A a, #B b) {}\n" + + "}\n"; + + String source; + + public JavaSource(String typeA, String typeB) { + super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); + source = sourceStub.replace("#A", typeA).replace("#B", typeB); + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return source; + } + } + + public static void main(String... args) throws Exception { + for (ClassType ctA : ClassType.values()) { + for (ParameterType ptA : ParameterType.values()) { + for (ClassType ctB : ClassType.values()) { + for (ParameterType ptB : ParameterType.values()) { + compileAndCheck(ptA, ctA, ptB, ctB); + } + } + } + } + } + + static void compileAndCheck(ParameterType ptA, ClassType ctA, ParameterType ptB, ClassType ctB) throws Exception { + JavaSource source = new JavaSource(ptA.instantiate(ctA), ptB.instantiate(ctB)); + final JavaCompiler tool = ToolProvider.getSystemJavaCompiler(); + JavacTask ct = (JavacTask)tool.getTask(null, null, null, + null, null, Arrays.asList(source)); + ct.setProcessors(Arrays.asList(new ContainTypesTester(ParameterType.contains(ptA, ctA, ptB, ctB), source))); + System.err.println("A = " + ptA +" / " + ptA.instantiate(ctA)); + System.err.println("B = " + ptB +" / " + ptB.instantiate(ctB)); + System.err.println("Source = " + source.source); + ct.analyze(); + } + + @SupportedSourceVersion(SourceVersion.RELEASE_7) + static class ContainTypesTester extends AbstractProcessor { + + boolean expected; + JavaSource source; + + ContainTypesTester(boolean expected, JavaSource source) { + this.expected = expected; + this.source = source; + } + + @Override + public Set getSupportedAnnotationTypes() { + Set supportedAnnos = new HashSet(); + supportedAnnos.add("*"); + return supportedAnnos; + } + + private void error(String msg) { + System.err.println(source.source); + throw new AssertionError(msg); + } + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + if (roundEnv.getRootElements().size() == 0) { + return true; + } + if (annotations.isEmpty() || annotations.size() > 1) { + error("no anno found/wrong number of annotations found: " + annotations.size()); + } + TypeElement anno = (TypeElement)annotations.toArray()[0]; + Set annoElems = roundEnv.getElementsAnnotatedWith(anno); + if (annoElems.isEmpty() || annoElems.size() > 1) { + error("no annotated element found/wrong number of annotated elements found: " + annoElems.size()); + } + Element annoElement = (Element)annoElems.toArray()[0]; + if (!(annoElement instanceof ExecutableElement)) { + error("annotated element must be a method"); + } + ExecutableElement method = (ExecutableElement)annoElement; + if (method.getParameters().size() != 2) { + error("annotated method must have 2 arguments"); + } + DeclaredType d1 = (DeclaredType)method.getParameters().get(0).asType(); + DeclaredType d2 = (DeclaredType)method.getParameters().get(1).asType(); + if (d1.getTypeArguments().size() != 1 || + d1.getTypeArguments().size() != 1) { + error("parameter type must be generic in one type-variable"); + } + TypeMirror t1 = d1.getTypeArguments().get(0); + TypeMirror t2 = d2.getTypeArguments().get(0); + + if (processingEnv.getTypeUtils().contains(t1, t2) != expected) { + error("bad type containment result\n" + + "t1 : " + t1 +"\n" + + "t2 : " + t2 +"\n" + + "expected answer : " + expected +"\n"); + } + return true; + } + } +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/api/TestGetElement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/api/TestGetElement.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2010, 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 6930507 + * @summary Symbols for anonymous and local classes made too late for use by java tree API + */ + +import java.io.*; +import java.util.*; +import javax.annotation.processing.*; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.*; +import javax.tools.Diagnostic; +import static javax.lang.model.util.ElementFilter.*; + +import com.sun.source.tree.*; +import com.sun.source.util.*; + +@SupportedOptions({"test", "last"}) +@SupportedAnnotationTypes("*") +public class TestGetElement extends AbstractProcessor { + public static void main(String... args) throws Exception { + new TestGetElement().run(); + } + + public TestGetElement() { } + + public void run() throws Exception { + final String testSrc = System.getProperty("test.src"); + final String testClasses = System.getProperty("test.classes"); + final String myClassName = getClass().getName(); + final String mySrc = new File(testSrc, myClassName + ".java").getPath(); + + final int NUM_TESTS = 90; // #decls in this source file + for (int i = 1; i <= NUM_TESTS; i++) { + System.err.println("test " + i); + File testDir = new File("test" + i); + File classesDir = new File(testDir, "classes"); + classesDir.mkdirs(); + String[] args = { + "-d", classesDir.getPath(), + "-processorpath", testClasses, + "-processor", myClassName, + "-proc:only", + "-Atest=" + i, + "-Alast=" + (i == NUM_TESTS), + mySrc + }; + +// System.err.println("compile: " + Arrays.asList(args)); + + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + int rc = com.sun.tools.javac.Main.compile(args, pw); + pw.close(); + String out = sw.toString(); + if (out != null) + System.err.println(out); + if (rc != 0) { + System.err.println("compilation failed: rc=" + rc); + errors++; + } + } + + if (errors > 0) + throw new Exception(errors + " errors occurred"); + } + + + int errors; + + public boolean process(Set annotations, + RoundEnvironment roundEnvironment) + { + if (roundEnvironment.processingOver()) + return true; + + Map options = processingEnv.getOptions(); + int test = Integer.parseInt(options.get("test")); + boolean _last = Boolean.parseBoolean(options.get("last")); + + Trees trees = Trees.instance(processingEnv); + Scanner scanner = new Scanner(trees, _last); + int nelems = 0; + for (TypeElement e : typesIn(roundEnvironment.getRootElements())) { + nelems += scanner.scan(trees.getPath(e), test); + } + + Messager m = processingEnv.getMessager(); + int EXPECT = 1; + if (nelems != EXPECT) { + m.printMessage(Diagnostic.Kind.ERROR, + "Unexpected number of elements found: " + nelems + " expected: " + EXPECT); + } + return true; + } + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } + + class Scanner extends TreePathScanner { + final Trees trees; + final boolean last; + int count; + + Scanner(Trees trees, boolean last) { + this.trees = trees; + this.last = last; + } + + @Override + public Integer visitClass(ClassTree tree, Integer test) { + return reduce(check(test), super.visitClass(tree, test)); + } + + @Override + public Integer visitMethod(MethodTree tree, Integer test) { + return reduce(check(test), super.visitMethod(tree, test)); + } + + @Override + public Integer visitVariable(VariableTree tree, Integer test) { + return reduce(check(test), super.visitVariable(tree, test)); + } + + @Override + public Integer reduce(Integer i1, Integer i2) { + if (i1 == null || i1.intValue() == 0) + return i2; + if (i2 == null || i2.intValue() == 0) + return i1; + return (i1 + i2); + } + + int check(int test) { + count++; + + if (count != test) + return 0; + + TreePath p = getCurrentPath(); + Element e = trees.getElement(p); + + String text = p.getLeaf().toString().replaceAll("\\s+", " ").trim(); + int MAXLEN = 40; + if (text.length() > MAXLEN) + text = text.substring(0, MAXLEN - 3) + "..."; + + System.err.println(String.format("%3d: %-" + MAXLEN + "s -- %s", + count, text, + (e == null ? "null" : e.getKind() + " " + e))); + + Messager m = processingEnv.getMessager(); + if (e == null) { + m.printMessage(Diagnostic.Kind.ERROR, "Null element found for " + text); + return 0; + } + + if (last && !e.getSimpleName().contentEquals("last")) { + m.printMessage(Diagnostic.Kind.ERROR, "Unexpected name in last test: " + + e.getSimpleName() + ", expected: last"); + } + + return 1; + } + } + + // following are all fodder for the test + + class MemberClass { + class NestedMemberClass { } + } + + { + class InnerClassInInit { } + Object o = new Object() { }; + } + + TestGetElement(TestGetElement unused) { + class InnerClassInConstr { } + Object o = new Object() { }; + } + + void m() { + class InnerClassInMethod { } + Object o = new Object() { }; + + class C { + class MemberClass { + class NestedMemberClass { } + } + + { + class InnerClassInInit { } + Object o = new Object() { }; + } + + C(Object unused) { + class InnerClassInConstr { } + Object o = new Object() { }; + } + + void m() { + class InnerClassInMethod { } + Object o = new Object() { }; + } + } + } + + int last; // this name is verified by the test to make sure that all decls are checked +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/api/ToolProvider/HelloWorldTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/api/ToolProvider/HelloWorldTest.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2010, 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 6604599 + * @summary ToolProvider should be less compiler-specific + */ + +import java.io.*; +import java.util.*; + +// verify that running a simple program, such as this one, does not trigger +// the loading of ToolProvider or any com.sun.tools.javac class +public class HelloWorldTest { + public static void main(String... args) throws Exception { + if (args.length > 0) { + System.err.println(Arrays.asList(args)); + return; + } + + new HelloWorldTest().run(); + } + + void run() throws Exception { + File javaHome = new File(System.getProperty("java.home")); + if (javaHome.getName().equals("jre")) + javaHome = javaHome.getParentFile(); + File javaExe = new File(new File(javaHome, "bin"), "java"); + String classpath = System.getProperty("java.class.path"); + + String[] cmd = { + javaExe.getPath(), + "-verbose:class", + "-classpath", classpath, + HelloWorldTest.class.getName(), + "Hello", "World" + }; + + ProcessBuilder pb = new ProcessBuilder(cmd).redirectErrorStream(true); + Process p = pb.start(); + BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream())); + String line; + while ((line = r.readLine()) != null) { + System.err.println(line); + if (line.contains("javax.tools.ToolProvider") || line.contains("com.sun.tools.javac.")) + error(">>> " + line); + } + int rc = p.waitFor(); + if (rc != 0) + error("Unexpected exit code: " + rc); + + if (errors > 0) + throw new Exception(errors + " errors occurred"); + } + + void error(String msg) { + System.err.println(msg); + errors++; + } + + int errors; +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/api/ToolProvider/ToolProviderTest1.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/api/ToolProvider/ToolProviderTest1.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2010, 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 6604599 + * @summary ToolProvider should be less compiler-specific + */ + +import java.io.*; + +// verify that running accessing ToolProvider by itself does not +// trigger loading com.sun.tools.javac.* +public class ToolProviderTest1 { + public static void main(String... args) throws Exception { + if (args.length > 0) { + System.err.println(Class.forName(args[0], true, null)); + return; + } + + new ToolProviderTest1().run(); + } + + void run() throws Exception { + File javaHome = new File(System.getProperty("java.home")); + if (javaHome.getName().equals("jre")) + javaHome = javaHome.getParentFile(); + File javaExe = new File(new File(javaHome, "bin"), "java"); + String classpath = System.getProperty("java.class.path"); + + String[] cmd = { + javaExe.getPath(), + "-verbose:class", + "-classpath", classpath, + ToolProviderTest1.class.getName(), + "javax.tools.ToolProvider" + }; + + ProcessBuilder pb = new ProcessBuilder(cmd).redirectErrorStream(true); + Process p = pb.start(); + BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream())); + String line; + while ((line = r.readLine()) != null) { + System.err.println(line); + if (line.contains("com.sun.tools.javac.")) + error(">>> " + line); + } + int rc = p.waitFor(); + if (rc != 0) + error("Unexpected exit code: " + rc); + + if (errors > 0) + throw new Exception(errors + " errors occurred"); + } + + void error(String msg) { + System.err.println(msg); + errors++; + } + + int errors; +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/api/ToolProvider/ToolProviderTest2.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/api/ToolProvider/ToolProviderTest2.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2010, 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 6604599 + * @summary ToolProvider should be less compiler-specific + */ + +import java.io.*; +import javax.tools.*; + +// control for ToolProviderTest1 -- verify that using ToolProvider to +// access the compiler does trigger loading com.sun.tools.javac.* +public class ToolProviderTest2 { + public static void main(String... args) throws Exception { + if (args.length > 0) { + System.err.println(ToolProvider.getSystemJavaCompiler()); + return; + } + + new ToolProviderTest2().run(); + } + + void run() throws Exception { + File javaHome = new File(System.getProperty("java.home")); + if (javaHome.getName().equals("jre")) + javaHome = javaHome.getParentFile(); + File javaExe = new File(new File(javaHome, "bin"), "java"); + String classpath = System.getProperty("java.class.path"); + + String[] cmd = { + javaExe.getPath(), + "-verbose:class", + "-classpath", classpath, + ToolProviderTest2.class.getName(), + "javax.tools.ToolProvider" + }; + + ProcessBuilder pb = new ProcessBuilder(cmd).redirectErrorStream(true); + Process p = pb.start(); + BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream())); + String line; + boolean found = false; + while ((line = r.readLine()) != null) { + System.err.println(line); + if (line.contains("com.sun.tools.javac.")) + found = true; + } + int rc = p.waitFor(); + if (rc != 0) + error("Unexpected exit code: " + rc); + + if (!found) + System.err.println("expected class name not found"); + + if (errors > 0) + throw new Exception(errors + " errors occurred"); + } + + void error(String msg) { + System.err.println(msg); + errors++; + } + + int errors; +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/diags/examples.not-yet.txt --- a/test/tools/javac/diags/examples.not-yet.txt Thu Sep 23 17:33:52 2010 -0700 +++ b/test/tools/javac/diags/examples.not-yet.txt Fri Sep 24 16:43:08 2010 -0700 @@ -62,6 +62,7 @@ compiler.misc.fatal.err.cant.locate.ctor # Resolve, from Lower compiler.misc.fatal.err.cant.locate.field # Resolve, from Lower compiler.misc.fatal.err.cant.locate.meth # Resolve, from Lower +compiler.misc.fatal.err.cant.close.loader # JavacProcessingEnvironment compiler.misc.file.does.not.contain.package compiler.misc.illegal.start.of.class.file compiler.misc.inferred.do.not.conform.to.params # UNUSED (hard to see if very complex inference scenario might require this though, so leaving it in, as per JLS3) @@ -113,3 +114,4 @@ compiler.warn.unchecked.assign # DEAD, replaced by compiler.misc.unchecked.assign compiler.warn.unchecked.cast.to.type # DEAD, replaced by compiler.misc.unchecked.cast.to.type compiler.warn.unexpected.archive.file # Paths: zip file with unknown extn +compiler.warn.wrong.target.for.polymorphic.signature.definition # Transitional 292 diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/diags/examples/TypeParameterOnPolymorphicSignature.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/diags/examples/TypeParameterOnPolymorphicSignature.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2010, 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. + */ + +// key: compiler.warn.type.parameter.on.polymorphic.signature +// key: compiler.err.unreported.exception.need.to.catch.or.throw + +import java.dyn.InvokeDynamic; + +class TypeParameterOnPolymorphicSignature { + { InvokeDynamic.call("",123); } +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/diags/examples/UnsupportedExoticID.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/diags/examples/UnsupportedExoticID.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2010, 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. + */ + +// key: compiler.err.unsupported.exotic.id +// options: -source 6 + +class UnsupportedExoticID { + void m() { + Object #"Hello!" = null; + } +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/failover/CheckAttributedTree.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/failover/CheckAttributedTree.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,775 @@ +/* + * Copyright (c) 2010, 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 com.sun.source.util.TaskEvent; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Font; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import javax.swing.DefaultComboBoxModel; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.JTextField; +import javax.swing.SwingUtilities; +import javax.swing.event.CaretEvent; +import javax.swing.event.CaretListener; +import javax.swing.text.BadLocationException; +import javax.swing.text.DefaultHighlighter; +import javax.swing.text.Highlighter; +import java.io.File; +import java.io.IOException; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.tools.Diagnostic; +import javax.tools.DiagnosticListener; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; + +import com.sun.source.tree.CompilationUnitTree; +import com.sun.source.util.JavacTask; +import com.sun.source.util.TaskListener; +import com.sun.tools.javac.api.JavacTool; +import com.sun.tools.javac.code.Symbol; +import com.sun.tools.javac.code.Type; +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.JCTree.JCClassDecl; +import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; +import com.sun.tools.javac.tree.JCTree.JCImport; +import com.sun.tools.javac.tree.TreeInfo; +import com.sun.tools.javac.tree.TreeScanner; +import com.sun.tools.javac.util.Pair; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import javax.lang.model.element.Element; + +/** + * Utility and test program to check validity of tree positions for tree nodes. + * The program can be run standalone, or as a jtreg test. In standalone mode, + * errors can be displayed in a gui viewer. For info on command line args, + * run program with no args. + * + *

+ * jtreg: Note that by using the -r switch in the test description below, this test + * will process all java files in the langtools/test directory, thus implicitly + * covering any new language features that may be tested in this test suite. + */ + +/* + * @test + * @bug 6970584 + * @summary assorted position errors in compiler syntax trees + * @run main CheckAttributedTree -q -r -et ERRONEOUS . + */ +public class CheckAttributedTree { + /** + * Main entry point. + * If test.src is set, program runs in jtreg mode, and will throw an Error + * if any errors arise, otherwise System.exit will be used, unless the gui + * viewer is being used. In jtreg mode, the default base directory for file + * args is the value of ${test.src}. In jtreg mode, the -r option can be + * given to change the default base directory to the root test directory. + */ + public static void main(String... args) { + String testSrc = System.getProperty("test.src"); + File baseDir = (testSrc == null) ? null : new File(testSrc); + boolean ok = new CheckAttributedTree().run(baseDir, args); + if (!ok) { + if (testSrc != null) // jtreg mode + throw new Error("failed"); + else + System.exit(1); + } + } + + /** + * Run the program. A base directory can be provided for file arguments. + * In jtreg mode, the -r option can be given to change the default base + * directory to the test root directory. For other options, see usage(). + * @param baseDir base directory for any file arguments. + * @param args command line args + * @return true if successful or in gui mode + */ + boolean run(File baseDir, String... args) { + if (args.length == 0) { + usage(System.out); + return true; + } + + List files = new ArrayList(); + for (int i = 0; i < args.length; i++) { + String arg = args[i]; + if (arg.equals("-encoding") && i + 1 < args.length) + encoding = args[++i]; + else if (arg.equals("-gui")) + gui = true; + else if (arg.equals("-q")) + quiet = true; + else if (arg.equals("-v")) + verbose = true; + else if (arg.equals("-t") && i + 1 < args.length) + tags.add(args[++i]); + else if (arg.equals("-ef") && i + 1 < args.length) + excludeFiles.add(new File(baseDir, args[++i])); + else if (arg.equals("-et") && i + 1 < args.length) + excludeTags.add(args[++i]); + else if (arg.equals("-r")) { + if (excludeFiles.size() > 0) + throw new Error("-r must be used before -ef"); + File d = baseDir; + while (!new File(d, "TEST.ROOT").exists()) { + if (d == null) + throw new Error("cannot find TEST.ROOT"); + d = d.getParentFile(); + } + baseDir = d; + } + else if (arg.startsWith("-")) + throw new Error("unknown option: " + arg); + else { + while (i < args.length) + files.add(new File(baseDir, args[i++])); + } + } + + for (File file: files) { + if (file.exists()) + test(file); + else + error("File not found: " + file); + } + + if (fileCount != 1) + System.err.println(fileCount + " files read"); + if (errors > 0) + System.err.println(errors + " errors"); + + return (gui || errors == 0); + } + + /** + * Print command line help. + * @param out output stream + */ + void usage(PrintStream out) { + out.println("Usage:"); + out.println(" java CheckAttributedTree options... files..."); + out.println(""); + out.println("where options include:"); + out.println("-q Quiet: don't report on inapplicable files"); + out.println("-gui Display returns in a GUI viewer"); + out.println("-v Verbose: report on files as they are being read"); + out.println("-t tag Limit checks to tree nodes with this tag"); + out.println(" Can be repeated if desired"); + out.println("-ef file Exclude file or directory"); + out.println("-et tag Exclude tree nodes with given tag name"); + out.println(""); + out.println("files may be directories or files"); + out.println("directories will be scanned recursively"); + out.println("non java files, or java files which cannot be parsed, will be ignored"); + out.println(""); + } + + /** + * Test a file. If the file is a directory, it will be recursively scanned + * for java files. + * @param file the file or directory to test + */ + void test(File file) { + if (excludeFiles.contains(file)) { + if (!quiet) + error("File " + file + " excluded"); + return; + } + + if (file.isDirectory()) { + for (File f: file.listFiles()) { + test(f); + } + return; + } + + if (file.isFile() && file.getName().endsWith(".java")) { + try { + if (verbose) + System.err.println(file); + fileCount++; + NPETester p = new NPETester(); + p.test(read(file)); + } catch (AttributionException e) { + if (!quiet) { + error("Error attributing " + file + "\n" + e.getMessage()); + } + } catch (IOException e) { + error("Error reading " + file + ": " + e); + } + return; + } + + if (!quiet) + error("File " + file + " ignored"); + } + + /** + * Read a file. + * @param file the file to be read + * @return the tree for the content of the file + * @throws IOException if any IO errors occur + * @throws TreePosTest.ParseException if any errors occur while parsing the file + */ + List> read(File file) throws IOException, AttributionException { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + Reporter r = new Reporter(pw); + JavacTool tool = JavacTool.create(); + Charset cs = (encoding == null ? null : Charset.forName(encoding)); + StandardJavaFileManager fm = tool.getStandardFileManager(r, null, null); + Iterable files = fm.getJavaFileObjects(file); + String[] opts = { "-XDshouldStopPolicy=ATTR", "-XDverboseCompilePolicy" }; + JavacTask task = tool.getTask(pw, fm, r, Arrays.asList(opts), null, files); + final List analyzedElems = new ArrayList<>(); + task.setTaskListener(new TaskListener() { + public void started(TaskEvent e) { + if (e.getKind() == TaskEvent.Kind.ANALYZE) + analyzedElems.add(e.getTypeElement()); + } + public void finished(TaskEvent e) { } + }); + + try { + Iterable trees = task.parse(); + task.analyze(); + List> res = new ArrayList<>(); + //System.out.println("Try to add pairs. Elems are " + analyzedElems); + for (CompilationUnitTree t : trees) { + JCCompilationUnit cu = (JCCompilationUnit)t; + for (JCTree def : cu.defs) { + if (def.getTag() == JCTree.CLASSDEF && + analyzedElems.contains(((JCTree.JCClassDecl)def).sym)) { + //System.out.println("Adding pair..."); + res.add(new Pair<>(cu, def)); + } + } + } + return res; + } + catch (Throwable t) { + throw new AttributionException("Exception while attributing file: " + file); + } + } + + /** + * Report an error. When the program is complete, the program will either + * exit or throw an Error if any errors have been reported. + * @param msg the error message + */ + void error(String msg) { + System.err.println(msg); + errors++; + } + + /** Number of files that have been analyzed. */ + int fileCount; + /** Number of errors reported. */ + int errors; + /** Flag: don't report irrelevant files. */ + boolean quiet; + /** Flag: show errors in GUI viewer. */ + boolean gui; + /** The GUI viewer for errors. */ + Viewer viewer; + /** Flag: report files as they are processed. */ + boolean verbose; + /** Option: encoding for test files. */ + String encoding; + /** The set of tags for tree nodes to be analyzed; if empty, all tree nodes + * are analyzed. */ + Set tags = new HashSet(); + /** Set of files and directories to be excluded from analysis. */ + Set excludeFiles = new HashSet(); + /** Set of tag names to be excluded from analysis. */ + Set excludeTags = new HashSet(); + /** Utility class for trees */ + TreeUtil treeUtil = new TreeUtil(); + + /** + * Main class for testing assertions concerning types/symbol + * left uninitialized after attribution + */ + private class NPETester extends TreeScanner { + void test(List> trees) { + for (Pair p : trees) { + sourcefile = p.fst.sourcefile; + endPosTable = p.fst.endPositions; + encl = new Info(p.snd, endPosTable); + p.snd.accept(this); + } + } + + @Override + public void scan(JCTree tree) { + if (tree == null || + excludeTags.contains(treeUtil.nameFromTag(tree.getTag()))) { + return; + } + + Info self = new Info(tree, endPosTable); + check(!mandatoryType(tree) || + (tree.type != null && + checkFields(tree)), + "'null' found in tree ", + self); + + Info prevEncl = encl; + encl = self; + tree.accept(this); + encl = prevEncl; + } + + private boolean mandatoryType(JCTree that) { + return that instanceof JCTree.JCExpression || + that.getTag() == JCTree.VARDEF || + that.getTag() == JCTree.METHODDEF || + that.getTag() == JCTree.CLASSDEF; + } + + private final List excludedFields = Arrays.asList("varargsElement"); + + void check(boolean ok, String label, Info self) { + if (!ok) { + if (gui) { + if (viewer == null) + viewer = new Viewer(); + viewer.addEntry(sourcefile, label, encl, self); + } + error(label + self.toString() + " encl: " + encl.toString() + " in file: " + sourcefile + " " + self.tree); + } + } + + boolean checkFields(JCTree t) { + List fieldsToCheck = treeUtil.getFieldsOfType(t, + excludedFields, + Symbol.class, + Type.class); + for (Field f : fieldsToCheck) { + try { + if (f.get(t) == null) { + return false; + } + } + catch (IllegalAccessException e) { + System.err.println("Cannot read field: " + f); + //swallow it + } + } + return true; + } + + @Override + public void visitImport(JCImport tree) { } + + @Override + public void visitTopLevel(JCCompilationUnit tree) { + scan(tree.defs); + } + + JavaFileObject sourcefile; + Map endPosTable; + Info encl; + } + + /** + * Utility class providing easy access to position and other info for a tree node. + */ + private class Info { + Info() { + tree = null; + tag = JCTree.ERRONEOUS; + start = 0; + pos = 0; + end = Integer.MAX_VALUE; + } + + Info(JCTree tree, Map endPosTable) { + this.tree = tree; + tag = tree.getTag(); + start = TreeInfo.getStartPos(tree); + pos = tree.pos; + end = TreeInfo.getEndPos(tree, endPosTable); + } + + @Override + public String toString() { + return treeUtil.nameFromTag(tree.getTag()) + "[start:" + start + ",pos:" + pos + ",end:" + end + "]"; + } + + final JCTree tree; + final int tag; + final int start; + final int pos; + final int end; + } + + /** + * Names for tree tags. + * javac does not provide an API to convert tag values to strings, so this class uses + * reflection to determine names of public static final int values in JCTree. + */ + private static class TreeUtil { + String nameFromTag(int tag) { + if (names == null) { + names = new HashMap(); + Class c = JCTree.class; + for (Field f : c.getDeclaredFields()) { + if (f.getType().equals(int.class)) { + int mods = f.getModifiers(); + if (Modifier.isPublic(mods) && Modifier.isStatic(mods) && Modifier.isFinal(mods)) { + try { + names.put(f.getInt(null), f.getName()); + } catch (IllegalAccessException e) { + } + } + } + } + } + String name = names.get(tag); + return (name == null) ? "??" : name; + } + + List getFieldsOfType(JCTree t, List excludeNames, Class... types) { + List buf = new ArrayList(); + for (Field f : t.getClass().getDeclaredFields()) { + if (!excludeNames.contains(f.getName())) { + for (Class type : types) { + if (type.isAssignableFrom(f.getType())) { + f.setAccessible(true); + buf.add(f); + break; + } + } + } + } + return buf; + } + + private Map names; + } + + /** + * Thrown when errors are found parsing a java file. + */ + private static class ParseException extends Exception { + ParseException(String msg) { + super(msg); + } + } + + private static class AttributionException extends Exception { + AttributionException(String msg) { + super(msg); + } + } + + /** + * DiagnosticListener to report diagnostics and count any errors that occur. + */ + private static class Reporter implements DiagnosticListener { + Reporter(PrintWriter out) { + this.out = out; + } + + public void report(Diagnostic diagnostic) { + out.println(diagnostic); + switch (diagnostic.getKind()) { + case ERROR: + errors++; + } + } + int errors; + PrintWriter out; + } + + /** + * GUI viewer for issues found by TreePosTester. The viewer provides a drop + * down list for selecting error conditions, a header area providing details + * about an error, and a text area with the ranges of text highlighted as + * appropriate. + */ + private class Viewer extends JFrame { + /** + * Create a viewer. + */ + Viewer() { + initGUI(); + } + + /** + * Add another entry to the list of errors. + * @param file The file containing the error + * @param check The condition that was being tested, and which failed + * @param encl the enclosing tree node + * @param self the tree node containing the error + */ + void addEntry(JavaFileObject file, String check, Info encl, Info self) { + Entry e = new Entry(file, check, encl, self); + DefaultComboBoxModel m = (DefaultComboBoxModel) entries.getModel(); + m.addElement(e); + if (m.getSize() == 1) + entries.setSelectedItem(e); + } + + /** + * Initialize the GUI window. + */ + private void initGUI() { + JPanel head = new JPanel(new GridBagLayout()); + GridBagConstraints lc = new GridBagConstraints(); + GridBagConstraints fc = new GridBagConstraints(); + fc.anchor = GridBagConstraints.WEST; + fc.fill = GridBagConstraints.HORIZONTAL; + fc.gridwidth = GridBagConstraints.REMAINDER; + + entries = new JComboBox(); + entries.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + showEntry((Entry) entries.getSelectedItem()); + } + }); + fc.insets.bottom = 10; + head.add(entries, fc); + fc.insets.bottom = 0; + head.add(new JLabel("check:"), lc); + head.add(checkField = createTextField(80), fc); + fc.fill = GridBagConstraints.NONE; + head.add(setBackground(new JLabel("encl:"), enclColor), lc); + head.add(enclPanel = new InfoPanel(), fc); + head.add(setBackground(new JLabel("self:"), selfColor), lc); + head.add(selfPanel = new InfoPanel(), fc); + add(head, BorderLayout.NORTH); + + body = new JTextArea(); + body.setFont(Font.decode(Font.MONOSPACED)); + body.addCaretListener(new CaretListener() { + public void caretUpdate(CaretEvent e) { + int dot = e.getDot(); + int mark = e.getMark(); + if (dot == mark) + statusText.setText("dot: " + dot); + else + statusText.setText("dot: " + dot + ", mark:" + mark); + } + }); + JScrollPane p = new JScrollPane(body, + JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, + JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); + p.setPreferredSize(new Dimension(640, 480)); + add(p, BorderLayout.CENTER); + + statusText = createTextField(80); + add(statusText, BorderLayout.SOUTH); + + pack(); + setLocationRelativeTo(null); // centered on screen + setVisible(true); + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + } + + /** Show an entry that has been selected. */ + private void showEntry(Entry e) { + try { + // update simple fields + setTitle(e.file.getName()); + checkField.setText(e.check); + enclPanel.setInfo(e.encl); + selfPanel.setInfo(e.self); + // show file text with highlights + body.setText(e.file.getCharContent(true).toString()); + Highlighter highlighter = body.getHighlighter(); + highlighter.removeAllHighlights(); + addHighlight(highlighter, e.encl, enclColor); + addHighlight(highlighter, e.self, selfColor); + scroll(body, getMinPos(enclPanel.info, selfPanel.info)); + } catch (IOException ex) { + body.setText("Cannot read " + e.file.getName() + ": " + e); + } + } + + /** Create a test field. */ + private JTextField createTextField(int width) { + JTextField f = new JTextField(width); + f.setEditable(false); + f.setBorder(null); + return f; + } + + /** Add a highlighted region based on the positions in an Info object. */ + private void addHighlight(Highlighter h, Info info, Color c) { + int start = info.start; + int end = info.end; + if (start == -1 && end == -1) + return; + if (start == -1) + start = end; + if (end == -1) + end = start; + try { + h.addHighlight(info.start, info.end, + new DefaultHighlighter.DefaultHighlightPainter(c)); + if (info.pos != -1) { + Color c2 = new Color(c.getRed(), c.getGreen(), c.getBlue(), (int)(.4f * 255)); // 40% + h.addHighlight(info.pos, info.pos + 1, + new DefaultHighlighter.DefaultHighlightPainter(c2)); + } + } catch (BadLocationException e) { + e.printStackTrace(); + } + } + + /** Get the minimum valid position in a set of info objects. */ + private int getMinPos(Info... values) { + int i = Integer.MAX_VALUE; + for (Info info: values) { + if (info.start >= 0) i = Math.min(i, info.start); + if (info.pos >= 0) i = Math.min(i, info.pos); + if (info.end >= 0) i = Math.min(i, info.end); + } + return (i == Integer.MAX_VALUE) ? 0 : i; + } + + /** Set the background on a component. */ + private JComponent setBackground(JComponent comp, Color c) { + comp.setOpaque(true); + comp.setBackground(c); + return comp; + } + + /** Scroll a text area to display a given position near the middle of the visible area. */ + private void scroll(final JTextArea t, final int pos) { + // Using invokeLater appears to give text a chance to sort itself out + // before the scroll happens; otherwise scrollRectToVisible doesn't work. + // Maybe there's a better way to sync with the text... + EventQueue.invokeLater(new Runnable() { + public void run() { + try { + Rectangle r = t.modelToView(pos); + JScrollPane p = (JScrollPane) SwingUtilities.getAncestorOfClass(JScrollPane.class, t); + r.y = Math.max(0, r.y - p.getHeight() * 2 / 5); + r.height += p.getHeight() * 4 / 5; + t.scrollRectToVisible(r); + } catch (BadLocationException ignore) { + } + } + }); + } + + private JComboBox entries; + private JTextField checkField; + private InfoPanel enclPanel; + private InfoPanel selfPanel; + private JTextArea body; + private JTextField statusText; + + private Color selfColor = new Color(0.f, 1.f, 0.f, 0.2f); // 20% green + private Color enclColor = new Color(1.f, 0.f, 0.f, 0.2f); // 20% red + + /** Panel to display an Info object. */ + private class InfoPanel extends JPanel { + InfoPanel() { + add(tagName = createTextField(20)); + add(new JLabel("start:")); + add(addListener(start = createTextField(6))); + add(new JLabel("pos:")); + add(addListener(pos = createTextField(6))); + add(new JLabel("end:")); + add(addListener(end = createTextField(6))); + } + + void setInfo(Info info) { + this.info = info; + tagName.setText(treeUtil.nameFromTag(info.tag)); + start.setText(String.valueOf(info.start)); + pos.setText(String.valueOf(info.pos)); + end.setText(String.valueOf(info.end)); + } + + JTextField addListener(final JTextField f) { + f.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + body.setCaretPosition(Integer.valueOf(f.getText())); + body.getCaret().setVisible(true); + } + }); + return f; + } + + Info info; + JTextField tagName; + JTextField start; + JTextField pos; + JTextField end; + } + + /** Object to record information about an error to be displayed. */ + private class Entry { + Entry(JavaFileObject file, String check, Info encl, Info self) { + this.file = file; + this.check = check; + this.encl = encl; + this.self= self; + } + + @Override + public String toString() { + return file.getName() + " " + check + " " + getMinPos(encl, self); + } + + final JavaFileObject file; + final String check; + final Info encl; + final Info self; + } + } +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/failover/FailOver01.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/failover/FailOver01.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,10 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6970584 + * @summary Flow.java should be more error-friendly + * @author mcimadamore + * + * @compile/fail/ref=FailOver01.out -XDrawDiagnostics -XDshouldStopPolicy=FLOW -XDdev FailOver01.java + */ + +class Test { { x = "" } } diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/failover/FailOver01.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/failover/FailOver01.out Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,3 @@ +FailOver01.java:10:22: compiler.err.expected: ';' +FailOver01.java:10:16: compiler.err.cant.resolve.location: kindname.variable, x, , , kindname.class, Test +2 errors diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/failover/FailOver02.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/failover/FailOver02.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,14 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6970584 + * @summary Flow.java should be more error-friendly + * @author mcimadamore + * + * @compile/fail/ref=FailOver02.out -XDrawDiagnostics -XDshouldStopPolicy=FLOW -XDdev FailOver02.java + */ + +class Test implements AutoCloseable { + void test() { + try(Test t = null) {} + } +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/failover/FailOver02.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/failover/FailOver02.out Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,3 @@ +FailOver02.java:10:1: compiler.err.does.not.override.abstract: Test, close(), java.lang.AutoCloseable +FailOver02.java:12:9: compiler.err.cant.resolve.location.args: kindname.method, close, , , kindname.class, Test +2 errors diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/failover/FailOver03.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/failover/FailOver03.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,12 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6970584 + * @summary Flow.java should be more error-friendly + * @author mcimadamore + * + * @compile/fail/ref=FailOver03.out -XDrawDiagnostics -XDshouldStopPolicy=FLOW -XDdev FailOver03.java + */ + +class Test extends Test { + Test i; +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/failover/FailOver03.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/failover/FailOver03.out Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,2 @@ +FailOver03.java:10:1: compiler.err.cyclic.inheritance: Test +1 error diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/failover/FailOver04.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/failover/FailOver04.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,12 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6970584 + * @summary Flow.java should be more error-friendly + * @author mcimadamore + * + * @compile/fail/ref=FailOver04.out -XDrawDiagnostics -XDshouldStopPolicy=FLOW -XDdev FailOver04.java + */ + +class Test { + { new Unknown() {}; } +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/failover/FailOver04.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/failover/FailOver04.out Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,2 @@ +FailOver04.java:11:10: compiler.err.cant.resolve.location: kindname.class, Unknown, , , kindname.class, Test +1 error diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/failover/FailOver05.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/failover/FailOver05.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,12 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6970584 + * @summary Flow.java should be more error-friendly + * @author mcimadamore + * + * @compile/fail/ref=FailOver05.out -XDrawDiagnostics -XDshouldStopPolicy=FLOW -XDdev FailOver05.java + */ + +class Test extends Test { + { for ( Integer x : null) {} } +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/failover/FailOver05.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/failover/FailOver05.out Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,2 @@ +FailOver05.java:10:1: compiler.err.cyclic.inheritance: Test +1 error diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/failover/FailOver06.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/failover/FailOver06.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,13 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6970584 + * @summary Flow.java should be more error-friendly + * @author mcimadamore + * + * @compile/fail/ref=FailOver06.out -XDrawDiagnostics -XDshouldStopPolicy=FLOW -XDdev FailOver06.java + */ + +class Test extends Test { + Inference x = 1; + { if (x == 1) { } else { } } +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/failover/FailOver06.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/failover/FailOver06.out Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,2 @@ +FailOver06.java:10:1: compiler.err.cyclic.inheritance: Test +1 error diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/failover/FailOver07.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/failover/FailOver07.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,13 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6970584 + * @summary Flow.java should be more error-friendly + * @author mcimadamore + * + * @compile/fail/ref=FailOver07.out -XDrawDiagnostics -XDshouldStopPolicy=FLOW -XDdev FailOver07.java + */ + +class Test extends Test { + Integer x = 1; + { do {} while (x); } +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/failover/FailOver07.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/failover/FailOver07.out Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,2 @@ +FailOver07.java:10:1: compiler.err.cyclic.inheritance: Test +1 error diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/failover/FailOver08.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/failover/FailOver08.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,13 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6970584 + * @summary Flow.java should be more error-friendly + * @author mcimadamore + * + * @compile/fail/ref=FailOver08.out -XDrawDiagnostics -XDshouldStopPolicy=FLOW -XDdev FailOver08.java + */ + +class Test extends Test { + Integer x = 1; + { while (x) {}; } +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/failover/FailOver08.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/failover/FailOver08.out Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,2 @@ +FailOver08.java:10:1: compiler.err.cyclic.inheritance: Test +1 error diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/failover/FailOver09.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/failover/FailOver09.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,13 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6970584 + * @summary Flow.java should be more error-friendly + * @author mcimadamore + * + * @compile/fail/ref=FailOver09.out -XDrawDiagnostics -XDshouldStopPolicy=FLOW -XDdev FailOver09.java + */ + +class Test extends Test { + Integer x = 1; + { for (x = 0 ; x ; x++) {}; } +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/failover/FailOver09.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/failover/FailOver09.out Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,2 @@ +FailOver09.java:10:1: compiler.err.cyclic.inheritance: Test +1 error diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/failover/FailOver10.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/failover/FailOver10.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,15 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6970584 + * @summary Flow.java should be more error-friendly + * @author mcimadamore + * + * @compile/fail/ref=FailOver10.out -XDrawDiagnostics -XDshouldStopPolicy=FLOW -XDdev FailOver10.java + */ + +class Test extends Test { + + boolean cond; + + { Object o = null; } +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/failover/FailOver10.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/failover/FailOver10.out Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,2 @@ +FailOver10.java:10:1: compiler.err.cyclic.inheritance: Test +1 error diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/failover/FailOver11.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/failover/FailOver11.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,17 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6970584 + * @summary Flow.java should be more error-friendly + * @author mcimadamore + * + * @compile/fail/ref=FailOver11.out -XDrawDiagnostics -XDshouldStopPolicy=FLOW -XDdev FailOver11.java + */ + +class Test extends Test { + + boolean cond; + + void m(Object o) {} + + { m(cond ? null : null); } +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/failover/FailOver11.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/failover/FailOver11.out Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,2 @@ +FailOver11.java:10:1: compiler.err.cyclic.inheritance: Test +1 error diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/failover/FailOver12.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/failover/FailOver12.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,15 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6970584 + * @summary Flow.java should be more error-friendly + * @author mcimadamore + * + * @compile/fail/ref=FailOver12.out -XDrawDiagnostics -XDshouldStopPolicy=FLOW -XDdev FailOver12.java + */ + +class Test extends Test { + + Integer x = 1; + + { try {} catch (Exception e) {} } +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/failover/FailOver12.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/failover/FailOver12.out Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,2 @@ +FailOver12.java:10:1: compiler.err.cyclic.inheritance: Test +1 error diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/failover/FailOver13.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/failover/FailOver13.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,15 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6970584 + * @summary Flow.java should be more error-friendly + * @author mcimadamore + * + * @compile/fail/ref=FailOver13.out -XDrawDiagnostics -XDshouldStopPolicy=FLOW -XDdev FailOver13.java + */ + +class Test extends Test { + + Integer x = 1; + + { x = (Object)o; } +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/failover/FailOver13.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/failover/FailOver13.out Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,2 @@ +FailOver13.java:10:1: compiler.err.cyclic.inheritance: Test +1 error diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/failover/FailOver14.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/failover/FailOver14.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,14 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6970584 + * @summary Flow.java should be more error-friendly + * @author mcimadamore + * + * @compile/fail/ref=FailOver14.out -XDrawDiagnostics -XDshouldStopPolicy=FLOW -XDdev FailOver14.java + */ + +class Test extends Test { + + { for (Integer x : !x) { } } + +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/failover/FailOver14.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/failover/FailOver14.out Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,2 @@ +FailOver14.java:10:1: compiler.err.cyclic.inheritance: Test +1 error diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/generics/OverrideBridge.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/generics/OverrideBridge.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2010, 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 6337171 + * @summary javac should create bridge methods when type variable bounds restricted + * @run main OverrideBridge + */ + +import java.io.*; +import java.net.URI; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.HashMap; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.SimpleJavaFileObject; +import javax.tools.ToolProvider; + +import com.sun.source.util.JavacTask; +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.ConstantPoolException; +import com.sun.tools.classfile.Descriptor.InvalidDescriptor; +import com.sun.tools.classfile.Method; + +public class OverrideBridge { + + enum Implementation { + IMPLICIT(""), + EXPLICIT("@Override public abstract X m(X x);"); + + String impl; + + Implementation(String impl) { + this.impl = impl; + } + } + + static class JavaSource extends SimpleJavaFileObject { + + final static String sourceStub = + "abstract class A {\n" + + " public abstract X m(X x);\n" + + "}\n" + + "interface I {\n" + + "X m(X x);\n" + + "}\n" + + "abstract class B> extends A implements I { #B }\n" + + "abstract class C> extends B { #C }\n" + + "abstract class D> extends C { #D }\n"; + + String source; + + public JavaSource(Implementation implB, Implementation implC, Implementation implD) { + super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); + source = sourceStub.replace("#B", implB.impl).replace("#C", implC.impl).replace("#D", implD.impl); + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return source; + } + } + + public static void main(String... args) throws Exception { + Map> refMembers = + compile(Implementation.EXPLICIT, Implementation.EXPLICIT, Implementation.EXPLICIT, "ref"); + int i = 0; + for (Implementation implB : Implementation.values()) { + for (Implementation implC : Implementation.values()) { + for (Implementation implD : Implementation.values()) { + Map> membersToCheck = compile(implB, implC, implD, "out_" + i++); + check(refMembers, membersToCheck); + } + } + } + } + + static String workDir = System.getProperty("user.dir"); + + static Map> compile(Implementation implB, Implementation implC, Implementation implD, String destPath) throws Exception { + File destDir = new File(workDir, destPath); destDir.mkdir(); + final JavaCompiler tool = ToolProvider.getSystemJavaCompiler(); + JavaSource source = new JavaSource(implB, implC, implD); + JavacTask ct = (JavacTask)tool.getTask(null, null, null, + Arrays.asList("-d", destPath), null, Arrays.asList(source)); + ct.generate(); + Map> members = new HashMap<>(); + addMembers(destDir, members); + return members; + } + + static void addMembers(File destDir, Map> members) { + String[] names = { "B.class", "C.class", "D.class" }; + try { + for (String name : names) { + File f = new File(destDir, name); + ClassFile cf = ClassFile.read(f); + members.put(cf, readMethod(cf, "m")); + } + } catch (Exception e) { + e.printStackTrace(); + throw new Error("error reading classes"); + } + } + + static List readMethod(ClassFile cf, String name) throws ConstantPoolException { + List buf = new ArrayList<>(); + for (Method m : cf.methods) { + if (m.getName(cf.constant_pool).equals(name)) { + buf.add(m); + } + } + return buf; + } + + static void check(Map> refMembers, Map> membersToCheck) throws ConstantPoolException, InvalidDescriptor { + for (Map.Entry> ref : refMembers.entrySet()) { + ClassFile cRef = ref.getKey(); + for (Method mRef : ref.getValue()) { + boolean ok = false; + for (Map.Entry> toCheck : membersToCheck.entrySet()) { + ClassFile cToCheck = toCheck.getKey(); + for (Method mToCheck : toCheck.getValue()) { + if (cRef.getName().equals(cToCheck.getName()) && + mRef.descriptor.getReturnType(cRef.constant_pool).equals( + mToCheck.descriptor.getReturnType(cToCheck.constant_pool)) && + mRef.descriptor.getParameterTypes(cRef.constant_pool).equals( + mToCheck.descriptor.getParameterTypes(cToCheck.constant_pool))) { + ok = true; + } + } + } + if (!ok) { + throw new AssertionError("Matching method descriptor for " + mRef.descriptor.getParameterTypes(cRef.constant_pool) + "not found"); + } + } + } + } +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/meth/InvokeDyn.java --- a/test/tools/javac/meth/InvokeDyn.java Thu Sep 23 17:33:52 2010 -0700 +++ b/test/tools/javac/meth/InvokeDyn.java Fri Sep 24 16:43:08 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2010, 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 @@ -23,12 +23,12 @@ /* * @test - * @bug 6754038 + * @bug 6754038 6979327 * @summary Generate call sites for method handle * @author jrose * * @library .. - * @compile -source 7 -target 7 InvokeDyn.java + * @compile -source 7 -target 7 -XDinvokedynamic -XDallowTransitionalJSR292=no InvokeDyn.java */ //No: @run main/othervm -XX:+EnableInvokeDynamic meth.InvokeDyn @@ -44,16 +44,21 @@ package meth; -import java.dyn.InvokeDynamic; +import java.dyn.*; public class InvokeDyn { + class CS extends CallSite { + CS(Object x, Object y, Object z) { throw new RuntimeException(); } + } + //@BootstrapMethod(CS.class) //note: requires 6964498 void test() throws Throwable { Object x = "hello"; - InvokeDynamic.greet(x, "world", 123); - InvokeDynamic.greet(x, "mundus", 456); - InvokeDynamic.greet(x, "kosmos", 789); - InvokeDynamic.cogitate(10.11121, 3.14); - InvokeDynamic.#"yow: what I mean to say is, please treat this one specially"(null); - InvokeDynamic.invoke("goodbye"); + Object ojunk; int ijunk; + ojunk = InvokeDynamic.greet(x, "world", 123); + ojunk = InvokeDynamic.greet(x, "mundus", 456); + ojunk = InvokeDynamic.greet(x, "kosmos", 789); + ojunk = (String) InvokeDynamic.cogitate(10.11121, 3.14); + InvokeDynamic.#"yow: what I mean to say is, please treat this one specially"(null); + ijunk = (int) InvokeDynamic.invoke("goodbye"); } } diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/meth/InvokeDynTrans.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/meth/InvokeDynTrans.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2008-2010, 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 6754038 6979327 + * @summary Generate call sites for method handle + * @author jrose + * + * @library .. + * @compile/fail/ref=InvokeDynTrans.out -Werror -XDrawDiagnostics -source 7 -target 7 InvokeDynTrans.java + */ +//No: @run main/othervm -XX:+EnableInvokeDynamic meth.InvokeDyn + +/* + * Standalone testing: + * + * $ cd $MY_REPO_DIR/langtools + * $ (cd make; make) + * $ ./dist/bootstrap/bin/javac -d dist test/tools/javac/meth/InvokeDyn.java + * $ javap -c -classpath dist meth.InvokeDyn + * + */ + +package meth; + +import java.dyn.InvokeDynamic; + +public class InvokeDynTrans { + void test() throws Throwable { + Object x = "hello"; + InvokeDynamic.greet(x, "world", 123); + InvokeDynamic.greet(x, "mundus", 456); + InvokeDynamic.greet(x, "kosmos", 789); + InvokeDynamic.cogitate(10.11121, 3.14); + InvokeDynamic.#"yow: what I mean to say is, please treat this one specially"(null); + InvokeDynamic.invoke("goodbye"); + } +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/meth/InvokeDynTrans.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/meth/InvokeDynTrans.out Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,6 @@ +InvokeDynTrans.java:55:39: compiler.warn.type.parameter.on.polymorphic.signature +InvokeDynTrans.java:56:91: compiler.warn.type.parameter.on.polymorphic.signature +InvokeDynTrans.java:57:34: compiler.warn.type.parameter.on.polymorphic.signature +- compiler.err.warnings.and.werror +1 error +3 warnings diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/meth/InvokeMH.java --- a/test/tools/javac/meth/InvokeMH.java Thu Sep 23 17:33:52 2010 -0700 +++ b/test/tools/javac/meth/InvokeMH.java Fri Sep 24 16:43:08 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2010, 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 @@ -23,11 +23,11 @@ /* * @test - * @bug 6754038 + * @bug 6754038 6979327 * @summary Generate call sites for method handle * @author jrose * - * @compile -source 7 -target 7 InvokeMH.java + * @compile -source 7 -target 7 -XDallowTransitionalJSR292=no InvokeMH.java */ /* @@ -57,20 +57,17 @@ Object k = "kosmos"; mh_SiO.invokeExact((String)k, 789); o = mh_SiO.invokeExact((String)null, 000); - o = mh_SiO.invokeExact("arda", -123); + o = (Object) mh_SiO.invokeExact("arda", -123); // sig = ()String - s = mh_vS.invokeExact(); + s = (String) mh_vS.invokeExact(); // sig = ()int - i = mh_vi.invokeExact(); - o = mh_vi.invokeExact(); - //s = mh_vi.invokeExact(); //BAD - mh_vi.invokeExact(); + i = (int) mh_vi.invokeExact(); + o = (int) mh_vi.invokeExact(); // sig = ()void - //o = mh_vv.invokeExact(); //BAD - mh_vv.invokeExact(); + mh_vv.invokeExact(); } void testGen(MethodHandle mh_SiO, @@ -80,24 +77,23 @@ Object o; String s; int i; // for return type testing // next five must have sig = (*,*)* - mh_SiO.invokeGeneric((Object)"world", (Object)123); - mh_SiO.invokeGeneric((Object)"mundus", (Object)456); + o = mh_SiO.invokeGeneric((Object)"world", (Object)123); + mh_SiO.invokeGeneric((Object)"mundus", (Object)456); Object k = "kosmos"; - mh_SiO.invokeGeneric(k, 789); + o = mh_SiO.invokeGeneric(k, 789); o = mh_SiO.invokeGeneric(null, 000); - o = mh_SiO.invokeGeneric("arda", -123); + o = mh_SiO.invokeGeneric("arda", -123); // sig = ()String o = mh_vS.invokeGeneric(); // sig = ()int - i = mh_vi.invokeGeneric(); - o = mh_vi.invokeGeneric(); - //s = mh_vi.invokeGeneric(); //BAD - mh_vi.invokeGeneric(); + i = (int) mh_vi.invokeGeneric(); + o = (int) mh_vi.invokeGeneric(); + mh_vi.invokeGeneric(); // sig = ()void - //o = mh_vv.invokeGeneric(); //BAD + mh_vv.invokeGeneric(); o = mh_vv.invokeGeneric(); } } diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/meth/InvokeMHTrans.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/meth/InvokeMHTrans.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,102 @@ +/* Copyright (c) 2008, 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 6754038 6979327 + * @summary Generate call sites for method handle + * @author jrose + * + * @compile/fail/ref=InvokeMHTrans.out -Werror -XDrawDiagnostics -source 7 -target 7 InvokeMHTrans.java + */ + +/* + * Standalone testing: + * + * $ cd $MY_REPO_DIR/langtools + * $ (cd make; make) + * $ ./dist/bootstrap/bin/javac -d dist test/tools/javac/meth/InvokeMH.java + * $ javap -c -classpath dist meth.InvokeMH + * + */ + +package meth; + +import java.dyn.MethodHandle; + +public class InvokeMHTrans { + void test(MethodHandle mh_SiO, + MethodHandle mh_vS, + MethodHandle mh_vi, + MethodHandle mh_vv) throws Throwable { + Object o; String s; int i; // for return type testing + + // next five must have sig = (String,int)Object + mh_SiO.invokeExact("world", 123); + mh_SiO.invokeExact("mundus", 456); + Object k = "kosmos"; + mh_SiO.invokeExact((String)k, 789); + o = mh_SiO.invokeExact((String)null, 000); + o = mh_SiO.invokeExact("arda", -123); + + // sig = ()String + s = mh_vS.invokeExact(); + + // sig = ()int + i = mh_vi.invokeExact(); + o = mh_vi.invokeExact(); + //s = mh_vi.invokeExact(); //BAD + mh_vi.invokeExact(); + + // sig = ()void + //o = mh_vv.invokeExact(); //BAD + mh_vv.invokeExact(); + } + + void testGen(MethodHandle mh_SiO, + MethodHandle mh_vS, + MethodHandle mh_vi, + MethodHandle mh_vv) throws Throwable { + Object o; String s; int i; // for return type testing + + // next five must have sig = (*,*)* + mh_SiO.invokeGeneric((Object)"world", (Object)123); + mh_SiO.invokeGeneric((Object)"mundus", (Object)456); + Object k = "kosmos"; + mh_SiO.invokeGeneric(k, 789); + o = mh_SiO.invokeGeneric(null, 000); + o = mh_SiO.invokeGeneric("arda", -123); + + // sig = ()String + o = mh_vS.invokeGeneric(); + + // sig = ()int + i = mh_vi.invokeGeneric(); + o = mh_vi.invokeGeneric(); + //s = mh_vi.invokeGeneric(); //BAD + mh_vi.invokeGeneric(); + + // sig = ()void + //o = mh_vv.invokeGeneric(); //BAD + o = mh_vv.invokeGeneric(); + } +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/meth/InvokeMHTrans.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/meth/InvokeMHTrans.out Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,13 @@ +InvokeMHTrans.java:59:39: compiler.warn.type.parameter.on.polymorphic.signature +InvokeMHTrans.java:62:38: compiler.warn.type.parameter.on.polymorphic.signature +InvokeMHTrans.java:65:35: compiler.warn.type.parameter.on.polymorphic.signature +InvokeMHTrans.java:66:35: compiler.warn.type.parameter.on.polymorphic.signature +InvokeMHTrans.java:68:31: compiler.warn.type.parameter.on.polymorphic.signature +InvokeMHTrans.java:72:32: compiler.warn.type.parameter.on.polymorphic.signature +InvokeMHTrans.java:83:35: compiler.warn.type.parameter.on.polymorphic.signature +InvokeMHTrans.java:87:41: compiler.warn.type.parameter.on.polymorphic.signature +InvokeMHTrans.java:93:37: compiler.warn.type.parameter.on.polymorphic.signature +InvokeMHTrans.java:96:34: compiler.warn.type.parameter.on.polymorphic.signature +- compiler.err.warnings.and.werror +1 error +10 warnings diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/meth/MakeNegTests.sh --- a/test/tools/javac/meth/MakeNegTests.sh Thu Sep 23 17:33:52 2010 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,98 +0,0 @@ -#!/bin/sh - -# -# Copyright (c) 2008, 2009, 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 6754038 -# @summary Verify correct rejection of strongly typed return values -# @run shell MakeNegTests.sh - -default_template=InvokeMH.java -javacflags='-source 7 -target 7' -# the rest of this file is a generic "//BAD"-line tester - -: ${TESTSRC=.} ${TESTCLASSES=.} -javac="${TESTJAVA+${TESTJAVA}/bin/}javac" - -verbose=false quiet=false - -main() { - case "${@-}" in - *.java*) - for template in "$@"; do - expand_and_test "$template" - done;; - *) expand_and_test "${TESTSRC}/$default_template";; - esac -} - -expand_and_test() { - template=$1 - expand "$@" - testneg "$@" -} - -expand() { - template=$1 - badlines=` grep -n < "$template" '//BAD' ` - badcount=` echo "$badlines" | wc -l ` - [ $badcount -gt 0 ] || { echo "No negative test cases in $template"; exit 1; } - $quiet || echo "Expanding $badcount negative test cases from $template:" - $quiet || echo "$badlines" - badnums=` echo "$badlines" | sed 's/:.*//' ` - casestem=` getcasestem "$template" ` - tclassname=` basename "$template" .java ` - rm -f "$casestem"*.java - for badnum in $badnums; do - casefile="$casestem"${badnum}.java - cclassname=` basename "$casefile" .java ` - sed < "$template" > "$casefile" " - s|@compile|@compile/fail| - / @[a-z]/s|@|##| - ${badnum}s:^ *[/*]*: : - s/${tclassname}/${cclassname}/g - " - $verbose && diff -u "$template" "$casefile" - done -} - -getcasestem() { - echo `basename $1` | sed 's/\.java$//;s/_BAD[0-9]*$//;s/$/_BAD/' -} - -testneg() { - template=$1 - for casefile in ` getcasestem "$template" `*.java; do - $quiet || echo -------- $javac $javacflags "$casefile" - $javac $javacflags "$casefile" > "$casefile".errlog 2>&1 && { - echo "*** Compilation unexpectedly succeeded: $casefile" - exit 1 - } - $quiet || echo "Compilation failed as expected" - $quiet || head ` $verbose || echo -3 ` < "$casefile".errlog - rm "$casefile".errlog - done -} - -main "$@" diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/parser/ExtraSemiTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/parser/ExtraSemiTest.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2010, 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 6921495 + * @summary spurious semicolons in class def cause empty NOPOS blocks + */ + +import java.io.*; +import java.net.*; +import java.util.*; +import javax.tools.*; +import com.sun.source.util.*; + +public class ExtraSemiTest { + + static class JavaSource extends SimpleJavaFileObject { + + final static String source = + "class C {\n" + + " int x;;\n" + + " class X { int i;; };\n" + + "}"; + + JavaSource() { + super(URI.create("myfo:/C.java"), JavaFileObject.Kind.SOURCE); + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return source; + } + } + + public static void main(String... args) throws IOException { + new ExtraSemiTest().run(); + } + + void run() throws IOException { + File destDir = new File("classes"); destDir.mkdir(); + final JavaCompiler tool = ToolProvider.getSystemJavaCompiler(); + JavaSource source = new JavaSource(); + JavacTask ct = (JavacTask)tool.getTask(null, null, null, + Arrays.asList("-d", destDir.getPath(), "-XD-printsource"), + null, + Arrays.asList(source)); + Boolean ok = ct.call(); + if (!ok) throw new AssertionError("compilation failed"); + + String text = readFile(new File(destDir, "C.java")); + System.out.println(text); + + // compress/canonicalize all whitespace + String canon = text.replaceAll("\\s+", " "); + System.out.println("canon: " + canon); + + // There are no empty blocks in the original text. + // C will be given a default constructor "C() { super(); }" which + // does not have any empty blocks. + // The bug is that spurious semicolons in the class defn are parsed + // into redundant empty blocks in the tree, so verify there are + // no empty blocks in the -printsource output + + if (canon.contains("{ }")) + throw new AssertionError("unexpected empty block found"); + } + + String readFile(File f) throws IOException { + int len = (int) f.length(); + byte[] data = new byte[len]; + DataInputStream in = new DataInputStream(new FileInputStream(f)); + try { + in.readFully(data); + return new String(data); + } finally { + in.close(); + } + } +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/processing/6430209/b6341534.java --- a/test/tools/javac/processing/6430209/b6341534.java Thu Sep 23 17:33:52 2010 -0700 +++ b/test/tools/javac/processing/6430209/b6341534.java Fri Sep 24 16:43:08 2010 -0700 @@ -51,7 +51,8 @@ try { PackageElement PE = E.getPackageElement("dir1"); List LEE = PE.getEnclosedElements(); /* <=This line elicits the error message. */ - for(Element e : LEE) System.out.println("found " + e.toString() + " in dir1."); + for(Element e : LEE) + System.out.println("found " + e.toString() + " in dir1."); } catch(NullPointerException npe) { msgr.printMessage(ERROR,npe.toString()); @@ -59,7 +60,11 @@ return false; } } - if( renv.errorRaised() ) { msgr.printMessage(ERROR, "FAILED");} + // on round 1, expect errorRaised == false && processingOver == false + // on round 2, expect errorRaised == true && processingOver == true + if( renv.errorRaised() != renv.processingOver()) { + msgr.printMessage(ERROR, "FAILED"); + } return true; } diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/processing/errors/TestSuppression.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/processing/errors/TestSuppression.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2010, 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 6403465 + * @summary javac should defer diagnostics until it can be determined they are persistent + */ + +import java.io.*; +import java.util.*; +import javax.annotation.processing.*; +import javax.lang.model.*; +import javax.lang.model.element.TypeElement; +import javax.tools.*; + +import com.sun.source.util.JavacTask; +import com.sun.tools.javac.api.JavacTool; +import com.sun.tools.javac.util.JCDiagnostic; + +import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag.*; + + +public class TestSuppression { + public static void main(String... args) throws Exception { + new TestSuppression().run(args); + } + + enum WarningKind { NO, YES }; + + String[] cases = { + // missing class C + "class X { C c; }", + "class X { C foo() { return null; } }", + "class X { void foo(C c) { } }", + "class X extends C { }", + "class X { }", + // missing interface I + "class X implements I { }", + "interface X extends I { }", + // missing exception E + "class X { void m() throws E { } }", + // missing method m + "class X extends C { int i = m(); }", + // missing field f + "class X extends C { int i = f; }" + }; + + void run(String... args) throws Exception { + for (String c: cases) { + for (WarningKind wk: WarningKind.values()) { + for (int g = 1; g <= 3; g++) { + try { + test(c, wk, g); + } catch (Throwable t) { + error("caught: " + t); + } + if (errors > 0) throw new AssertionError(); + } + } + } + + System.err.println(count + " test cases"); + + if (errors > 0) + throw new Exception(errors + " errors occurred"); + } + + void test(String src, WarningKind wk, int gen) throws Exception { + count++; + System.err.println("Test " + count + ": wk:" + wk + " gen:" + gen + " src:" +src); + + File testDir = new File("test" + count); + File srcDir = createDir(testDir, "src"); + File gensrcDir = createDir(testDir, "gensrc"); + File classesDir = createDir(testDir, "classes"); + + File x = writeFile(new File(srcDir, "X.java"), src); + + DiagListener dl = new DiagListener(); + JavacTool tool = JavacTool.create(); + StandardJavaFileManager fm = tool.getStandardFileManager(dl, null, null); + fm.setLocation(StandardLocation.CLASS_PATH, + Arrays.asList(classesDir, new File(System.getProperty("test.classes")))); + fm.setLocation(StandardLocation.CLASS_OUTPUT, Collections.singleton(classesDir)); + fm.setLocation(StandardLocation.SOURCE_OUTPUT, Collections.singleton(gensrcDir)); + List args = new ArrayList(); +// args.add("-XprintProcessorInfo"); + args.add("-XprintRounds"); + args.add("-Agen=" + gen); + if (wk == WarningKind.YES) + args.add("-Xlint:serial"); + Iterable files = fm.getJavaFileObjects(x); + + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + JavacTask task = tool.getTask(pw, fm, dl, args, null, files); + task.setProcessors(Arrays.asList(new AnnoProc())); + boolean ok = task.call(); + pw.close(); + + System.err.println("ok:" + ok + " diags:" + dl.counts); + if (sw.toString().length() > 0) { + System.err.println("output:\n" + sw.toString()); + } + + for (Diagnostic.Kind dk: Diagnostic.Kind.values()) { + Integer v = dl.counts.get(dk); + int found = (v == null) ? 0 : v; + int expect = (dk == Diagnostic.Kind.WARNING && wk == WarningKind.YES) ? gen : 0; + if (found != expect) { + error("Unexpected value for " + dk + ": expected: " + expect + " found: " + found); + } + } + + System.err.println(); + } + + File createDir(File parent, String name) { + File dir = new File(parent, name); + dir.mkdirs(); + return dir; + } + + File writeFile(File f, String content) throws IOException { + FileWriter out = new FileWriter(f); + try { + out.write(content); + } finally { + out.close(); + } + return f; + } + + void add(List list, T... values) { + for (T v: values) + list.add(v); + } + + void error(String msg) { + System.err.println("Error: " + msg); + errors++; + } + + int count; + int errors; + + static class DiagListener implements DiagnosticListener { + int total; + Map counts = new TreeMap(); + + public void report(Diagnostic diagnostic) { + System.err.println((++total) + ": " + + "resolveError:" + isResolveError((JCDiagnostic) diagnostic) + "\n" + + diagnostic); + Diagnostic.Kind dk = diagnostic.getKind(); + Integer c = counts.get(dk); + counts.put(dk, (c == null ? 1 : c + 1)); + } + + private static boolean isResolveError(JCDiagnostic d) { + return d.isFlagSet(RESOLVE_ERROR); + } + } + + @SupportedAnnotationTypes("*") + @SupportedOptions("gen") + public static class AnnoProc extends AbstractProcessor { + Filer f; + Messager m; + int gen; + + @Override + public void init(ProcessingEnvironment processingEnv) { + f = processingEnv.getFiler(); + m = processingEnv.getMessager(); + Map options = processingEnv.getOptions(); + gen = Integer.parseInt(options.get("gen")); + } + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + round++; + if (round < gen) + writeSource("Dummy" + round, "class Dummy" + round + " extends java.util.ArrayList{ }"); + else if (round == gen) { + writeSource("C", "class C { int f; int m() { return 0; } }"); + writeSource("I", "interface I { }"); + writeSource("E", "class E extends Exception { }"); + } + return true; + } + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } + + private void writeSource(String name, String text) { + try { + JavaFileObject fo = f.createSourceFile(name); + Writer out = fo.openWriter(); + out.write(text); + out.close(); + } catch (IOException e) { + m.printMessage(Diagnostic.Kind.ERROR, e.toString()); + } + } + + int round = 0; + } +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/processing/filer/TestGetResource2.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/processing/filer/TestGetResource2.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2006, 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 6929404 + * @summary Filer.getResource(SOURCE_PATH, ...) does not work when -sourcepath contains >1 entry + */ + +import java.io.*; +import java.security.*; +import java.util.*; +import javax.annotation.processing.*; +import javax.lang.model.*; +import javax.lang.model.element.*; +import javax.tools.*; +import javax.tools.Diagnostic.Kind; +import javax.tools.JavaCompiler.CompilationTask; + +public class TestGetResource2 { + + public static void main(String[] args) throws Exception { + new TestGetResource2().run(); + } + + void run() throws Exception { + JavaCompiler javac = ToolProvider.getSystemJavaCompiler(); + CodeSource cs = javac.getClass().getProtectionDomain().getCodeSource(); + if (cs == null) { + System.err.println("got compiler from " + + ClassLoader.getSystemResource(javac.getClass().getName().replace(".", "/")+".class")); + } else { + System.err.println("got compiler from " + cs.getLocation()); + } + + testSingleSourceDir(javac); + testCompositeSourcePath(javac); + testMissingResource(javac); + } + + private void testSingleSourceDir(JavaCompiler javac) throws Exception { + System.err.println("testSingleSourceDir"); + File tmpdir = new File("testSingleSourceDir"); + File srcdir = new File(tmpdir, "src"); + File destdir = new File(tmpdir, "dest"); + write(srcdir, "pkg/X.java", "package pkg; class X {}"); + write(srcdir, "resources/file.txt", "hello"); + destdir.mkdirs(); + + CompilationTask task = javac.getTask(null, null, null, + Arrays.asList("-sourcepath", srcdir.toString(), "-d", destdir.toString()), + Collections.singleton("pkg.X"), null); + task.setProcessors(Collections.singleton(new AnnoProc())); + boolean result = task.call(); + System.err.println("javac result with single source dir: " + result); + expect(result, true); + } + + private void testCompositeSourcePath(JavaCompiler javac) throws Exception { + System.err.println("testCompositeSearchPath"); + File tmpdir = new File("testCompositeSourcePath"); + File srcdir = new File(tmpdir, "src"); + File rsrcdir = new File(tmpdir, "rsrc"); + File destdir = new File(tmpdir, "dest"); + write(srcdir, "pkg/X.java", "package pkg; class X {}"); + write(rsrcdir, "resources/file.txt", "hello"); + destdir.mkdirs(); + + CompilationTask task = javac.getTask(null, null, null, + Arrays.asList("-sourcepath", srcdir + File.pathSeparator + rsrcdir, "-d", destdir.toString()), + Collections.singleton("pkg.X"), null); + task.setProcessors(Collections.singleton(new AnnoProc())); + boolean result = task.call(); + System.err.println("javac result with composite source path: " + result); + expect(result, true); + } + + private void testMissingResource(JavaCompiler javac) throws Exception { + System.err.println("testMissingResource"); + File tmpdir = new File("testMissingResource"); + File srcdir = new File(tmpdir, "src"); + File destdir = new File(tmpdir, "dest"); + write(srcdir, "pkg/X.java", "package pkg; class X {}"); + destdir.mkdirs(); + + CompilationTask task = javac.getTask(null, null, null, + Arrays.asList("-sourcepath", srcdir.toString(), "-d", destdir.toString()), + Collections.singleton("pkg.X"), null); + task.setProcessors(Collections.singleton(new AnnoProc())); + boolean result = task.call(); + System.err.println("javac result when missing resource: " + result); + expect(result, false); + + if (errors > 0) + throw new Exception(errors + " errors occurred"); + } + + @SupportedAnnotationTypes("*") + static class AnnoProc extends AbstractProcessor { + + public @Override boolean process(Set annotations, RoundEnvironment roundEnv) { + if (roundEnv.processingOver()) { + return false; + } + + try { + FileObject resource = processingEnv.getFiler().getResource(StandardLocation.SOURCE_PATH, "resources", "file.txt"); + try { + resource.openInputStream().close(); + processingEnv.getMessager().printMessage(Kind.NOTE, "found: " + resource.toUri()); + return true; + } catch (IOException x) { + processingEnv.getMessager().printMessage(Kind.ERROR, "could not read: " + resource.toUri()); + x.printStackTrace(); + } + } catch (IOException x) { + processingEnv.getMessager().printMessage(Kind.ERROR, "did not find resource"); + x.printStackTrace(); + } + + return false; + } + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } + } + + private File write(File dir, String path, String contents) throws IOException { + File f = new File(dir, path); + f.getParentFile().mkdirs(); + Writer w = new FileWriter(f); + try { + w.write(contents); + } finally { + w.close(); + } + return f; + } + + void expect(boolean val, boolean expect) { + if (val != expect) + error("Unexpected value: " + val + "; expected: " + expect); + } + + void error(String msg) { + System.err.println(msg); + errors++; + } + + int errors = 0; +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/processing/model/element/TestAnonClassNames.java --- a/test/tools/javac/processing/model/element/TestAnonClassNames.java Thu Sep 23 17:33:52 2010 -0700 +++ b/test/tools/javac/processing/model/element/TestAnonClassNames.java Fri Sep 24 16:43:08 2010 -0700 @@ -27,8 +27,7 @@ * @summary Test that reported names of anonymous classes are non-null. * @author Joseph D. Darcy * @build TestAnonSourceNames - * @compile/fail -processor TestAnonSourceNames TestAnonClassNames.java - * @build TestAnonClassNames + * @compile -processor TestAnonSourceNames TestAnonClassNames.java * @run main TestAnonClassNames */ @@ -40,10 +39,6 @@ * * Source files will be tested by the @compile line which runs * TestAnonSourceNames as an annotation processor over this file. - * This compile line is expected to fail until 6930507 is fixed. Once - * bug 6930507 is fixed, the "@compile/fail -processor ..." and - * following "@build..." steps can be replaced with a single "@compile - * -processor ..." directive. * * Class files are tested by the @run command on this type. This * class gets the names of classes with different nesting kinds, diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/processing/model/element/TestAnonSourceNames.java --- a/test/tools/javac/processing/model/element/TestAnonSourceNames.java Thu Sep 23 17:33:52 2010 -0700 +++ b/test/tools/javac/processing/model/element/TestAnonSourceNames.java Fri Sep 24 16:43:08 2010 -0700 @@ -67,7 +67,7 @@ Element element = trees.getElement(trees.getPath(cu, node)); if (element == null) { processingEnv.getMessager().printMessage(ERROR, - "No element retreived for node named ''" + + "No element retrieved for node named ''" + node.getSimpleName() + "''."); } else { diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/processing/options/TestImplicitNone.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/processing/options/TestImplicitNone.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2010, 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 6935638 + * @summary -implicit:none prevents compilation with annotation processing + */ + +import java.io.*; +import java.util.*; +import javax.annotation.processing.*; +import javax.lang.model.*; +import javax.lang.model.element.*; + + +@SupportedAnnotationTypes("*") +public class TestImplicitNone extends AbstractProcessor { + public static void main(String... args) throws Exception { + new TestImplicitNone().run(); + } + + void run() throws Exception { + File classesDir = new File("tmp", "classes"); + classesDir.mkdirs(); + File test_java = new File(new File("tmp", "src"), "Test.java"); + writeFile(test_java, "class Test { }"); + + // build up list of options and files to be compiled + List opts = new ArrayList(); + List files = new ArrayList(); + + opts.add("-d"); + opts.add(classesDir.getPath()); + opts.add("-processorpath"); + opts.add(System.getProperty("test.classes")); + opts.add("-implicit:none"); + opts.add("-processor"); + opts.add(TestImplicitNone.class.getName()); + files.add(test_java); + + compile(opts, files); + + File test_class = new File(classesDir, "Test.class"); + if (!test_class.exists()) + throw new Exception("Test.class not generated"); + } + + /** Compile files with options provided. */ + void compile(List opts, List files) throws Exception { + System.err.println("javac: " + opts + " " + files); + List args = new ArrayList(); + args.addAll(opts); + for (File f: files) + args.add(f.getPath()); + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + int rc = com.sun.tools.javac.Main.compile(args.toArray(new String[args.size()]), pw); + pw.flush(); + if (sw.getBuffer().length() > 0) + System.err.println(sw.toString()); + if (rc != 0) + throw new Exception("compilation failed: rc=" + rc); + } + + /** Write a file with a given body. */ + void writeFile(File f, String body) throws Exception { + if (f.getParentFile() != null) + f.getParentFile().mkdirs(); + Writer out = new FileWriter(f); + try { + out.write(body); + } finally { + out.close(); + } + } + + //----- annotation processor methods ----- + + public boolean process(Set annotations, + RoundEnvironment roundEnv) { + return true; + } + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/quid/MakeNegTests.sh --- a/test/tools/javac/quid/MakeNegTests.sh Thu Sep 23 17:33:52 2010 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,97 +0,0 @@ -#!/bin/sh - -# -# Copyright (c) 2008, 2009, 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 6746458 -# @summary Verify correct rejection of illegal quoted identifiers. -# @run shell MakeNegTests.sh - -default_template=QuotedIdent.java -# the rest of this file is a generic "//BAD"-line tester - -: ${TESTSRC=.} ${TESTCLASSES=.} -javac="${TESTJAVA+${TESTJAVA}/bin/}javac" - -verbose=false quiet=false - -main() { - case "${@-}" in - *.java*) - for template in "$@"; do - expand_and_test "$template" - done;; - *) expand_and_test "${TESTSRC}/$default_template";; - esac -} - -expand_and_test() { - template=$1 - expand "$@" - testneg "$@" -} - -expand() { - template=$1 - badlines=` grep -n < "$template" '//BAD' ` - badcount=` echo "$badlines" | wc -l ` - [ $badcount -gt 0 ] || { echo "No negative test cases in $template"; exit 1; } - $quiet || echo "Expanding $badcount negative test cases from $template:" - $quiet || echo "$badlines" - badnums=` echo "$badlines" | sed 's/:.*//' ` - casestem=` getcasestem "$template" ` - tclassname=` basename "$template" .java ` - rm "$casestem"*.java - for badnum in $badnums; do - casefile="$casestem"${badnum}.java - cclassname=` basename "$casefile" .java ` - sed < "$template" > "$casefile" " - s|@compile|@compile/fail| - / @[a-z]/s|@|##| - ${badnum}s:^ *[/*]*: : - s/${tclassname}/${cclassname}/g - " - $verbose && diff -u "$template" "$casefile" - done -} - -getcasestem() { - echo `basename $1` | sed 's/.*\///;s/\.java$//;s/_BAD[0-9]*$//;s/$/_BAD/' -} - -testneg() { - template=$1 - for casefile in ` getcasestem "$template" `*.java; do - $quiet || echo -------- $javac "$casefile" - $javac "$casefile" > "$casefile".errlog 2>&1 && { - echo "*** Compilation unexpectedly succeeded: $casefile" - exit 1 - } - $quiet || echo "Compilation failed as expected" - $quiet || head ` $verbose || echo -3 ` < "$casefile".errlog - rm "$casefile".errlog - done -} - -main "$@" diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/quid/QuotedIdent.java --- a/test/tools/javac/quid/QuotedIdent.java Thu Sep 23 17:33:52 2010 -0700 +++ b/test/tools/javac/quid/QuotedIdent.java Fri Sep 24 16:43:08 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2010, 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 @@ -31,6 +31,7 @@ * (The filename, directory name, or volume label syntax is incorrect) * * @library .. + * @compile -source 7 -target 7 -XDinvokedynamic QuotedIdent.java * @run main quid.QuotedIdent */ @@ -119,7 +120,7 @@ s = #"int".class.getName(); check(31, s, QuotedIdent.class.getName()+"$int"); - Class x86 = Class.forName(QuotedIdent.class.getName()+"$*86"); + Class x86 = Class.forName(QuotedIdent.class.getName()+"$*86"); if (x86 != #"*86".class) check(32, "reflected "+x86, "static "+#"*86".class); diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/quid/QuotedIdent2.java --- a/test/tools/javac/quid/QuotedIdent2.java Thu Sep 23 17:33:52 2010 -0700 +++ b/test/tools/javac/quid/QuotedIdent2.java Fri Sep 24 16:43:08 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2010, 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 @@ -31,6 +31,7 @@ * (The filename, directory name, or volume label syntax is incorrect) * * @library .. + * @compile -source 7 -target 7 -XDinvokedynamic QuotedIdent.java * @run main quid.QuotedIdent2 */ /* @@ -72,7 +73,7 @@ s = QuotedIdent.#"int".class.getName(); check(31, s, QuotedIdent.class.getName()+"$int"); - Class x86 = Class.forName(QuotedIdent.class.getName()+"$*86"); + Class x86 = Class.forName(QuotedIdent.class.getName()+"$*86"); if (x86 != #"*86".class) check(32, "reflected "+x86, "static "+#"*86".class); diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/tree/AbstractTreeScannerTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/tree/AbstractTreeScannerTest.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2010, 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.lang.reflect.*; +import java.util.*; +import javax.tools.*; + +import com.sun.source.tree.CompilationUnitTree; +import com.sun.source.tree.Tree; +import com.sun.source.util.JavacTask; +import com.sun.tools.javac.api.JavacTool; +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; +import com.sun.tools.javac.util.List; + +public abstract class AbstractTreeScannerTest { + + /** + * Run the program. A base directory can be provided for file arguments. + * In jtreg mode, the -r option can be given to change the default base + * directory to the test root directory. For other options, see usage(). + * @param baseDir base directory for any file arguments. + * @param args command line args + * @return true if successful or in gui mode + */ + boolean run(File baseDir, String... args) { + if (args.length == 0) { + usage(System.out); + return true; + } + + ArrayList files = new ArrayList(); + for (int i = 0; i < args.length; i++) { + String arg = args[i]; + if (arg.equals("-q")) + quiet = true; + else if (arg.equals("-v")) + verbose = true; + else if (arg.equals("-r")) { + File d = baseDir; + while (!new File(d, "TEST.ROOT").exists()) { + d = d.getParentFile(); + if (d == null) + throw new Error("cannot find TEST.ROOT"); + } + baseDir = d; + } + else if (arg.startsWith("-")) + throw new Error("unknown option: " + arg); + else { + while (i < args.length) + files.add(new File(baseDir, args[i++])); + } + } + + for (File file: files) { + if (file.exists()) + test(file); + else + error("File not found: " + file); + } + + if (fileCount != 1) + System.err.println(fileCount + " files read"); + System.err.println(treeCount + " tree nodes compared"); + if (errors > 0) + System.err.println(errors + " errors"); + + return (errors == 0); + } + + /** + * Print command line help. + * @param out output stream + */ + void usage(PrintStream out) { + out.println("Usage:"); + out.println(" java " + getClass().getName() + " options... files..."); + out.println(""); + out.println("where options include:"); + out.println("-q Quiet: don't report on inapplicable files"); + out.println("-v Verbose: report on files as they are being read"); + out.println(""); + out.println("files may be directories or files"); + out.println("directories will be scanned recursively"); + out.println("non java files, or java files which cannot be parsed, will be ignored"); + out.println(""); + } + + /** + * Test a file. If the file is a directory, it will be recursively scanned + * for java files. + * @param file the file or directory to test + */ + void test(File file) { + if (file.isDirectory()) { + for (File f: file.listFiles()) { + test(f); + } + return; + } + + if (file.isFile() && file.getName().endsWith(".java")) { + try { + if (verbose) + System.err.println(file); + fileCount++; + treeCount += test(read(file)); + } catch (ParseException e) { + if (!quiet) { + error("Error parsing " + file + "\n" + e.getMessage()); + } + } catch (IOException e) { + error("Error reading " + file + ": " + e); + } + return; + } + + if (!quiet) + error("File " + file + " ignored"); + } + + abstract int test(JCCompilationUnit t); + + /** + * Read a file. + * @param file the file to be read + * @return the tree for the content of the file + * @throws IOException if any IO errors occur + * @throws TreePosTest.ParseException if any errors occur while parsing the file + */ + JCCompilationUnit read(File file) throws IOException, ParseException { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + Reporter r = new Reporter(pw); + JavacTool tool = JavacTool.create(); + StandardJavaFileManager fm = tool.getStandardFileManager(r, null, null); + Iterable files = fm.getJavaFileObjects(file); + JavacTask task = tool.getTask(pw, fm, r, Collections.emptyList(), null, files); + Iterable trees = task.parse(); + pw.flush(); + if (r.errors > 0) + throw new ParseException(sw.toString()); + Iterator iter = trees.iterator(); + if (!iter.hasNext()) + throw new Error("no trees found"); + JCCompilationUnit t = (JCCompilationUnit) iter.next(); + if (iter.hasNext()) + throw new Error("too many trees found"); + return t; + } + + /** + * Report an error. When the program is complete, the program will either + * exit or throw an Error if any errors have been reported. + * @param msg the error message + */ + void error(String msg) { + System.err.println(msg); + errors++; + } + + /** + * Report an error. When the program is complete, the program will either + * exit or throw an Error if any errors have been reported. + * @param msg the error message + */ + void error(JavaFileObject file, String msg) { + System.err.println(file.getName() + ": " + msg); + errors++; + } + + /** + * Report an error for a specific tree node. + * @param file the source file for the tree + * @param t the tree node + * @param label an indication of the error + */ + void error(JavaFileObject file, Tree tree, String msg) { + JCTree t = (JCTree) tree; + error(file.getName() + ":" + getLine(file, t) + ": " + msg + " " + trim(t, 64)); + } + + /** + * Get a trimmed string for a tree node, with normalized white space and limited length. + */ + String trim(Tree tree, int len) { + JCTree t = (JCTree) tree; + String s = t.toString().replaceAll("\\s+", " "); + return (s.length() < len) ? s : s.substring(0, len); + } + + /** Number of files that have been analyzed. */ + int fileCount; + /** Number of trees that have been successfully compared. */ + int treeCount; + /** Number of errors reported. */ + int errors; + /** Flag: don't report irrelevant files. */ + boolean quiet; + /** Flag: report files as they are processed. */ + boolean verbose; + + + /** + * Thrown when errors are found parsing a java file. + */ + private static class ParseException extends Exception { + ParseException(String msg) { + super(msg); + } + } + + /** + * DiagnosticListener to report diagnostics and count any errors that occur. + */ + private static class Reporter implements DiagnosticListener { + Reporter(PrintWriter out) { + this.out = out; + } + + public void report(Diagnostic diagnostic) { + out.println(diagnostic); + switch (diagnostic.getKind()) { + case ERROR: + errors++; + } + } + int errors; + PrintWriter out; + } + + /** + * Get the set of fields for a tree node that may contain child tree nodes. + * These are the fields that are subtypes of JCTree or List. + * The results are cached, based on the tree's tag. + */ + Set getFields(JCTree tree) { + Set fields = map.get(tree.getTag()); + if (fields == null) { + fields = new HashSet(); + for (Field f: tree.getClass().getFields()) { + Class fc = f.getType(); + if (JCTree.class.isAssignableFrom(fc) || List.class.isAssignableFrom(fc)) + fields.add(f); + } + map.put(tree.getTag(), fields); + } + return fields; + } + // where + Map> map = new HashMap>(); + + /** Get the line number for the primary position for a tree. + * The code is intended to be simple, although not necessarily efficient. + * However, note that a file manager such as JavacFileManager is likely + * to cache the results of file.getCharContent, avoiding the need to read + * the bits from disk each time this method is called. + */ + int getLine(JavaFileObject file, JCTree tree) { + try { + CharSequence cs = file.getCharContent(true); + int line = 1; + for (int i = 0; i < tree.pos; i++) { + if (cs.charAt(i) == '\n') // jtreg tests always use Unix line endings + line++; + } + return line; + } catch (IOException e) { + return -1; + } + } +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/tree/ClassTreeTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/tree/ClassTreeTest.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2010, 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 6570730 + * @summary com.sun.source.tree.ModifiersTree.getFlags() should return class type + */ + +import java.io.*; +import java.util.*; +import javax.tools.*; +import com.sun.source.tree.*; +import com.sun.source.util.*; +import com.sun.tools.javac.api.*; + +public class ClassTreeTest { + public static void main(String... args) throws Exception { + new ClassTreeTest().run(); + } + + void run() throws Exception { + JavacTool tool = JavacTool.create(); + StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null); + List opts = Collections.emptyList(); + File testSrc = new File(System.getProperty("test.src")); + File thisFile = new File(testSrc, ClassTreeTest.class.getSimpleName() + ".java"); + Iterable fos = fm.getJavaFileObjects(thisFile); + JavacTask task = tool.getTask(null, fm, null, opts, null, fos); + for (CompilationUnitTree cu: task.parse()) { + check(cu, "CLASS", Tree.Kind.CLASS); + check(cu, "INTERFACE", Tree.Kind.INTERFACE); + check(cu, "ENUM", Tree.Kind.ENUM); + check(cu, "ANNOTATION_TYPE", Tree.Kind.ANNOTATION_TYPE); + } + + int expected = 4; + if (checks != expected) + error("Unexpected number of checks performed; expected: " + expected + ", found: " + checks); + + if (errors > 0) + throw new Exception(errors + " errors found"); + } + + void check(CompilationUnitTree cu, String name, Tree.Kind k) { + checks++; + + TreeScanner s = new TreeScanner() { + @Override + public ClassTree visitClass(ClassTree c, String name) { + if (c.getSimpleName().toString().equals(name)) + return c; + else + return super.visitClass(c, name); + } + + @Override + public ClassTree reduce(ClassTree t1, ClassTree t2) { + return (t1 != null ? t1 : t2); + } + }; + + ClassTree c = s.scan(cu, name); + if (c == null) + error("Can't find node named " + name); + else if (c.getKind() != k) + error("Unexpected kind for node named " + name + ": expected: " + k + ", found: " + c.getKind()); + } + + void error(String msg) { + System.err.println("Error: " + msg); + errors++; + } + + int checks; + int errors; + + class CLASS { } + interface INTERFACE { } + enum ENUM { } + @interface ANNOTATION_TYPE { } +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/tree/JavacTreeScannerTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/tree/JavacTreeScannerTest.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2010, 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. + */ + + +/** + * Utility and test program to check javac's internal TreeScanner class. + * The program can be run standalone, or as a jtreg test. For info on + * command line args, run program with no args. + * + *

+ * jtreg: Note that by using the -r switch in the test description below, this test + * will process all java files in the langtools/test directory, thus implicitly + * covering any new language features that may be tested in this test suite. + */ + +/* + * @test + * @bug 6923080 + * @summary TreeScanner.visitNewClass should scan tree.typeargs + * @build AbstractTreeScannerTest JavacTreeScannerTest + * @run main JavacTreeScannerTest -q -r . + */ + +import java.io.*; +import java.lang.reflect.*; +import java.util.*; +import javax.tools.*; + +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; +import com.sun.tools.javac.tree.TreeScanner; +import com.sun.tools.javac.util.List; + +public class JavacTreeScannerTest extends AbstractTreeScannerTest { + /** + * Main entry point. + * If test.src is set, program runs in jtreg mode, and will throw an Error + * if any errors arise, otherwise System.exit will be used. In jtreg mode, + * the default base directory for file args is the value of ${test.src}. + * In jtreg mode, the -r option can be given to change the default base + * directory to the root test directory. + */ + public static void main(String... args) { + String testSrc = System.getProperty("test.src"); + File baseDir = (testSrc == null) ? null : new File(testSrc); + boolean ok = new JavacTreeScannerTest().run(baseDir, args); + if (!ok) { + if (testSrc != null) // jtreg mode + throw new Error("failed"); + else + System.exit(1); + } + } + + int test(JCCompilationUnit tree) { + return new ScanTester().test(tree); + } + + /** + * Main class for testing operation of tree scanner. + * The set of nodes found by the scanner are compared + * against the set of nodes found by reflection. + */ + private class ScanTester extends TreeScanner { + /** Main entry method for the class. */ + int test(JCCompilationUnit tree) { + sourcefile = tree.sourcefile; + found = new HashSet(); + scan(tree); + expect = new HashSet(); + reflectiveScan(tree); + + if (found.equals(expect)) { + //System.err.println(sourcefile.getName() + ": trees compared OK"); + return found.size(); + } + + error(sourcefile, "differences found"); + + if (found.size() != expect.size()) + error("Size mismatch; found: " + found.size() + ", expected: " + expect.size()); + + Set missing = new HashSet(); + missing.addAll(expect); + missing.removeAll(found); + for (JCTree t: missing) + error(sourcefile, t, "missing"); + + Set excess = new HashSet(); + excess.addAll(found); + excess.removeAll(expect); + for (JCTree t: excess) + error(sourcefile, t, "unexpected"); + + return 0; + } + + /** Record all tree nodes found by scanner. */ + @Override + public void scan(JCTree tree) { + if (tree == null) + return; + //System.err.println("FOUND: " + tree.getTag() + " " + trim(tree, 64)); + found.add(tree); + super.scan(tree); + } + + /** record all tree nodes found by reflection. */ + public void reflectiveScan(Object o) { + if (o == null) + return; + if (o instanceof JCTree) { + JCTree tree = (JCTree) o; + //System.err.println("EXPECT: " + tree.getTag() + " " + trim(tree, 64)); + expect.add(tree); + for (Field f: getFields(tree)) { + try { + //System.err.println("FIELD: " + f.getName()); + reflectiveScan(f.get(tree)); + } catch (IllegalAccessException e) { + error(e.toString()); + } + } + } else if (o instanceof List) { + List list = (List) o; + for (Object item: list) + reflectiveScan(item); + } else + error("unexpected item: " + o); + } + + JavaFileObject sourcefile; + Set found; + Set expect; + } +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/tree/SourceTreeScannerTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/tree/SourceTreeScannerTest.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2010, 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. + */ + + +/** + * Utility and test program to check javac's internal TreeScanner class. + * The program can be run standalone, or as a jtreg test. For info on + * command line args, run program with no args. + * + *

+ * jtreg: Note that by using the -r switch in the test description below, this test + * will process all java files in the langtools/test directory, thus implicitly + * covering any new language features that may be tested in this test suite. + */ + +/* + * @test + * @bug 6923080 + * @summary TreeScanner.visitNewClass should scan tree.typeargs + * @build AbstractTreeScannerTest SourceTreeScannerTest + * @run main SourceTreeScannerTest -q -r . + */ + +import java.io.*; +import java.lang.reflect.*; +import java.util.*; +import javax.tools.*; + +import com.sun.source.tree.Tree; +import com.sun.source.util.TreeScanner; +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; +import com.sun.tools.javac.tree.JCTree.TypeBoundKind; +import com.sun.tools.javac.util.List; + +public class SourceTreeScannerTest extends AbstractTreeScannerTest { + /** + * Main entry point. + * If test.src is set, program runs in jtreg mode, and will throw an Error + * if any errors arise, otherwise System.exit will be used. In jtreg mode, + * the default base directory for file args is the value of ${test.src}. + * In jtreg mode, the -r option can be given to change the default base + * directory to the root test directory. + */ + public static void main(String... args) { + String testSrc = System.getProperty("test.src"); + File baseDir = (testSrc == null) ? null : new File(testSrc); + boolean ok = new SourceTreeScannerTest().run(baseDir, args); + if (!ok) { + if (testSrc != null) // jtreg mode + throw new Error("failed"); + else + System.exit(1); + } + } + + int test(JCCompilationUnit tree) { + return new ScanTester().test(tree); + } + + /** + * Main class for testing operation of tree scanner. + * The set of nodes found by the scanner are compared + * against the set of nodes found by reflection. + */ + private class ScanTester extends TreeScanner { + /** Main entry method for the class. */ + int test(JCCompilationUnit tree) { + sourcefile = tree.sourcefile; + found = new HashSet(); + scan(tree, null); + expect = new HashSet(); + reflectiveScan(tree); + + if (found.equals(expect)) { + //System.err.println(sourcefile.getName() + ": trees compared OK"); + return found.size(); + } + + error(sourcefile.getName() + ": differences found"); + + if (found.size() != expect.size()) + error("Size mismatch; found: " + found.size() + ", expected: " + expect.size()); + + Set missing = new HashSet(); + missing.addAll(expect); + missing.removeAll(found); + for (Tree t: missing) + error(sourcefile, t, "missing"); + + Set excess = new HashSet(); + excess.addAll(found); + excess.removeAll(expect); + for (Tree t: excess) + error(sourcefile, t, "unexpected"); + + return 0; + } + + /** Record all tree nodes found by scanner. */ + @Override + public Void scan(Tree tree, Void ignore) { + if (tree == null) + return null; + //System.err.println("FOUND: " + tree.getKind() + " " + trim(tree, 64)); + found.add(tree); + return super.scan(tree, ignore); + } + + /** record all tree nodes found by reflection. */ + public void reflectiveScan(Object o) { + if (o == null) + return; + if (o instanceof JCTree) { + JCTree tree = (JCTree) o; + //System.err.println("EXPECT: " + tree.getKind() + " " + trim(tree, 64)); + expect.add(tree); + for (Field f: getFields(tree)) { + if (TypeBoundKind.class.isAssignableFrom(f.getType())) { + // not part of public API + continue; + } + if (JCTree.JCNewArray.class.isAssignableFrom(tree.getClass()) + && (f.getName().equals("annotations") + || f.getName().equals("dimAnnotations"))) { + // these fields are incorrectly missing from the public API + // (CR 6983297) + continue; + } + try { + //System.err.println("FIELD: " + f.getName()); + reflectiveScan(f.get(tree)); + } catch (IllegalAccessException e) { + error(e.toString()); + } + } + } else if (o instanceof List) { + List list = (List) o; + for (Object item: list) + reflectiveScan(item); + } else + error("unexpected item: " + o); + } + + JavaFileObject sourcefile; + Set found; + Set expect; + } +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/tree/TreeKindTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/tree/TreeKindTest.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2006, 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 6341023 + * @summary Tree API: Tree.Kind should have mapping to interface + */ + +import com.sun.source.tree.*; + +public class TreeKindTest{ + public static void main(String... args) { + boolean ok = true; + + for (Tree.Kind k: Tree.Kind.values()) { + //System.err.println(k + " " + k.asInterface()); + Class i = k.asInterface(); + switch (k) { + case POSTFIX_INCREMENT: + case POSTFIX_DECREMENT: + case PREFIX_INCREMENT: + case PREFIX_DECREMENT: + case UNARY_PLUS: + case UNARY_MINUS: + case BITWISE_COMPLEMENT: + case LOGICAL_COMPLEMENT: + ok = ok & verify(k, i, i == UnaryTree.class); + break; + + case MULTIPLY: + case DIVIDE: + case REMAINDER: + case PLUS: + case MINUS: + case LEFT_SHIFT: + case RIGHT_SHIFT: + case UNSIGNED_RIGHT_SHIFT: + case LESS_THAN: + case GREATER_THAN: + case LESS_THAN_EQUAL: + case GREATER_THAN_EQUAL: + case EQUAL_TO: + case NOT_EQUAL_TO: + case AND: + case XOR: + case OR: + case CONDITIONAL_AND: + case CONDITIONAL_OR: + ok = ok & verify(k, i, i == BinaryTree.class); + break; + + case MULTIPLY_ASSIGNMENT: + case DIVIDE_ASSIGNMENT: + case REMAINDER_ASSIGNMENT: + case PLUS_ASSIGNMENT: + case MINUS_ASSIGNMENT: + case LEFT_SHIFT_ASSIGNMENT: + case RIGHT_SHIFT_ASSIGNMENT: + case UNSIGNED_RIGHT_SHIFT_ASSIGNMENT: + case AND_ASSIGNMENT: + case XOR_ASSIGNMENT: + case OR_ASSIGNMENT: + ok = ok & verify(k, i, i == CompoundAssignmentTree.class); + break; + + case INT_LITERAL: + case LONG_LITERAL: + case FLOAT_LITERAL: + case DOUBLE_LITERAL: + case BOOLEAN_LITERAL: + case CHAR_LITERAL: + case STRING_LITERAL: + case NULL_LITERAL: + ok = ok & verify(k, i, i == LiteralTree.class); + break; + + case UNBOUNDED_WILDCARD: + case EXTENDS_WILDCARD: + case SUPER_WILDCARD: + ok = ok & verify(k, i, i == WildcardTree.class); + break; + + case INTERFACE: + case ANNOTATION_TYPE: + case ENUM: + case CLASS: + ok = ok & verify(k, i, i == ClassTree.class); + break; + + case OTHER: + ok = ok & verify(k, i, i == null); + break; + + default: + String ks = k.toString().replace("_", "") + "tree"; + String iName = i.getName(); + String is = iName.substring(iName.lastIndexOf(".") + 1); + ok = ok & verify(k, i, ks.equalsIgnoreCase(is)); + } + } + + if (!ok) + throw new AssertionError("test failed"); + } + + static boolean verify(Tree.Kind k, Class c, boolean b) { + if (!b) + System.err.println("error: " + k + " " + c); + return b; + } +} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javac/tree/TreeScannerTest.java --- a/test/tools/javac/tree/TreeScannerTest.java Thu Sep 23 17:33:52 2010 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,387 +0,0 @@ -/* - * Copyright (c) 2010, 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. - */ - - -/** - * Utility and test program to check javac's internal TreeScanner class. - * The program can be run standalone, or as a jtreg test. For info on - * command line args, run program with no args. - * - *

- * jtreg: Note that by using the -r switch in the test description below, this test - * will process all java files in the langtools/test directory, thus implicitly - * covering any new language features that may be tested in this test suite. - */ - -/* - * @test - * @bug 6923080 - * @summary TreeScanner.visitNewClass should scan tree.typeargs - * @run main TreeScannerTest -q -r . - */ - -import java.io.*; -import java.lang.reflect.*; -import java.util.*; -import javax.tools.*; - -import com.sun.source.tree.CompilationUnitTree; -import com.sun.source.util.JavacTask; -import com.sun.tools.javac.api.JavacTool; -import com.sun.tools.javac.tree.*; -import com.sun.tools.javac.tree.JCTree.*; -import com.sun.tools.javac.util.List; - -public class TreeScannerTest { - /** - * Main entry point. - * If test.src is set, program runs in jtreg mode, and will throw an Error - * if any errors arise, otherwise System.exit will be used. In jtreg mode, - * the default base directory for file args is the value of ${test.src}. - * In jtreg mode, the -r option can be given to change the default base - * directory to the root test directory. - */ - public static void main(String... args) { - String testSrc = System.getProperty("test.src"); - File baseDir = (testSrc == null) ? null : new File(testSrc); - boolean ok = new TreeScannerTest().run(baseDir, args); - if (!ok) { - if (testSrc != null) // jtreg mode - throw new Error("failed"); - else - System.exit(1); - } - } - - /** - * Run the program. A base directory can be provided for file arguments. - * In jtreg mode, the -r option can be given to change the default base - * directory to the test root directory. For other options, see usage(). - * @param baseDir base directory for any file arguments. - * @param args command line args - * @return true if successful or in gui mode - */ - boolean run(File baseDir, String... args) { - if (args.length == 0) { - usage(System.out); - return true; - } - - ArrayList files = new ArrayList(); - for (int i = 0; i < args.length; i++) { - String arg = args[i]; - if (arg.equals("-q")) - quiet = true; - else if (arg.equals("-v")) - verbose = true; - else if (arg.equals("-r")) { - File d = baseDir; - while (!new File(d, "TEST.ROOT").exists()) { - d = d.getParentFile(); - if (d == null) - throw new Error("cannot find TEST.ROOT"); - } - baseDir = d; - } - else if (arg.startsWith("-")) - throw new Error("unknown option: " + arg); - else { - while (i < args.length) - files.add(new File(baseDir, args[i++])); - } - } - - for (File file: files) { - if (file.exists()) - test(file); - else - error("File not found: " + file); - } - - if (fileCount != 1) - System.err.println(fileCount + " files read"); - if (errors > 0) - System.err.println(errors + " errors"); - - return (errors == 0); - } - - /** - * Print command line help. - * @param out output stream - */ - void usage(PrintStream out) { - out.println("Usage:"); - out.println(" java TreeScannerTest options... files..."); - out.println(""); - out.println("where options include:"); - out.println("-q Quiet: don't report on inapplicable files"); - out.println("-v Verbose: report on files as they are being read"); - out.println(""); - out.println("files may be directories or files"); - out.println("directories will be scanned recursively"); - out.println("non java files, or java files which cannot be parsed, will be ignored"); - out.println(""); - } - - /** - * Test a file. If the file is a directory, it will be recursively scanned - * for java files. - * @param file the file or directory to test - */ - void test(File file) { - if (file.isDirectory()) { - for (File f: file.listFiles()) { - test(f); - } - return; - } - - if (file.isFile() && file.getName().endsWith(".java")) { - try { - if (verbose) - System.err.println(file); - fileCount++; - ScanTester t = new ScanTester(); - t.test(read(file)); - } catch (ParseException e) { - if (!quiet) { - error("Error parsing " + file + "\n" + e.getMessage()); - } - } catch (IOException e) { - error("Error reading " + file + ": " + e); - } - return; - } - - if (!quiet) - error("File " + file + " ignored"); - } - - /** - * Read a file. - * @param file the file to be read - * @return the tree for the content of the file - * @throws IOException if any IO errors occur - * @throws TreePosTest.ParseException if any errors occur while parsing the file - */ - JCCompilationUnit read(File file) throws IOException, ParseException { - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - Reporter r = new Reporter(pw); - JavacTool tool = JavacTool.create(); - StandardJavaFileManager fm = tool.getStandardFileManager(r, null, null); - Iterable files = fm.getJavaFileObjects(file); - JavacTask task = tool.getTask(pw, fm, r, Collections.emptyList(), null, files); - Iterable trees = task.parse(); - pw.flush(); - if (r.errors > 0) - throw new ParseException(sw.toString()); - Iterator iter = trees.iterator(); - if (!iter.hasNext()) - throw new Error("no trees found"); - JCCompilationUnit t = (JCCompilationUnit) iter.next(); - if (iter.hasNext()) - throw new Error("too many trees found"); - return t; - } - - /** - * Report an error. When the program is complete, the program will either - * exit or throw an Error if any errors have been reported. - * @param msg the error message - */ - void error(String msg) { - System.err.println(msg); - errors++; - } - - /** - * Report an error for a specific tree node. - * @param file the source file for the tree - * @param t the tree node - * @param label an indication of the error - */ - void error(JavaFileObject file, JCTree t, String msg) { - error(file.getName() + ":" + getLine(file, t) + ": " + msg + " " + trim(t, 64)); - } - - /** - * Get a trimmed string for a tree node, with normalized white space and limited length. - */ - String trim(JCTree t, int len) { - String s = t.toString().replaceAll("[\r\n]+", " ").replaceAll(" +", " "); - return (s.length() < len) ? s : s.substring(0, len); - } - - /** Number of files that have been analyzed. */ - int fileCount; - /** Number of errors reported. */ - int errors; - /** Flag: don't report irrelevant files. */ - boolean quiet; - /** Flag: report files as they are processed. */ - boolean verbose; - - /** - * Main class for testing operation of tree scanner. - * The set of nodes found by the scanner are compared - * against the set of nodes found by reflection. - */ - private class ScanTester extends TreeScanner { - /** Main entry method for the class. */ - void test(JCCompilationUnit tree) { - sourcefile = tree.sourcefile; - found = new HashSet(); - scan(tree); - expect = new HashSet(); - reflectiveScan(tree); - if (found.equals(expect)) - return; - - error("Differences found for " + tree.sourcefile.getName()); - - if (found.size() != expect.size()) - error("Size mismatch; found: " + found.size() + ", expected: " + expect.size()); - - Set missing = new HashSet(); - missing.addAll(expect); - missing.removeAll(found); - for (JCTree t: missing) - error(tree.sourcefile, t, "missing"); - - Set excess = new HashSet(); - excess.addAll(found); - excess.removeAll(expect); - for (JCTree t: excess) - error(tree.sourcefile, t, "unexpected"); - } - - /** Record all tree nodes found by scanner. */ - @Override - public void scan(JCTree tree) { - if (tree == null) - return; - System.err.println("FOUND: " + tree.getTag() + " " + trim(tree, 64)); - found.add(tree); - super.scan(tree); - } - - /** record all tree nodes found by reflection. */ - public void reflectiveScan(Object o) { - if (o == null) - return; - if (o instanceof JCTree) { - JCTree tree = (JCTree) o; - System.err.println("EXPECT: " + tree.getTag() + " " + trim(tree, 64)); - expect.add(tree); - for (Field f: getFields(tree)) { - try { - //System.err.println("FIELD: " + f.getName()); - reflectiveScan(f.get(tree)); - } catch (IllegalAccessException e) { - error(e.toString()); - } - } - } else if (o instanceof List) { - List list = (List) o; - for (Object item: list) - reflectiveScan(item); - } else - error("unexpected item: " + o); - } - - JavaFileObject sourcefile; - Set found; - Set expect; - } - - /** - * Thrown when errors are found parsing a java file. - */ - private static class ParseException extends Exception { - ParseException(String msg) { - super(msg); - } - } - - /** - * DiagnosticListener to report diagnostics and count any errors that occur. - */ - private static class Reporter implements DiagnosticListener { - Reporter(PrintWriter out) { - this.out = out; - } - - public void report(Diagnostic diagnostic) { - out.println(diagnostic); - switch (diagnostic.getKind()) { - case ERROR: - errors++; - } - } - int errors; - PrintWriter out; - } - - /** - * Get the set of fields for a tree node that may contain child tree nodes. - * These are the fields that are subtypes of JCTree or List. - * The results are cached, based on the tree's tag. - */ - Set getFields(JCTree tree) { - Set fields = map.get(tree.getTag()); - if (fields == null) { - fields = new HashSet(); - for (Field f: tree.getClass().getFields()) { - Class fc = f.getType(); - if (JCTree.class.isAssignableFrom(fc) || List.class.isAssignableFrom(fc)) - fields.add(f); - } - map.put(tree.getTag(), fields); - } - return fields; - } - // where - Map> map = new HashMap>(); - - /** Get the line number for the primary position for a tree. - * The code is intended to be simple, although not necessarily efficient. - * However, note that a file manager such as JavacFileManager is likely - * to cache the results of file.getCharContent, avoiding the need to read - * the bits from disk each time this method is called. - */ - int getLine(JavaFileObject file, JCTree tree) { - try { - CharSequence cs = file.getCharContent(true); - int line = 1; - for (int i = 0; i < tree.pos; i++) { - if (cs.charAt(i) == '\n') // jtreg tests always use Unix line endings - line++; - } - return line; - } catch (IOException e) { - return -1; - } - } -} diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javap/T6868539.java --- a/test/tools/javap/T6868539.java Thu Sep 23 17:33:52 2010 -0700 +++ b/test/tools/javap/T6868539.java Fri Sep 24 16:43:08 2010 -0700 @@ -39,25 +39,25 @@ } void run() { - verify("T6868539", "Utf8 +java/lang/String"); // 1: Utf8 + String output = javap("T6868539"); + verify(output, "Utf8 +java/lang/String"); // 1: Utf8 // 2: currently unused - verify("T6868539", "Integer +123456"); // 3: Integer - verify("T6868539", "Float +123456.0f"); // 4: Float - verify("T6868539", "Long +123456l"); // 5: Long - verify("T6868539", "Double +123456.0d"); // 6: Double - verify("T6868539", "Class +#[0-9]+ +// + T6868539"); // 7: Class - verify("T6868539", "String +#[0-9]+ +// + not found"); // 8: String - verify("T6868539", "Fieldref +#[0-9]+\\.#[0-9]+ +// +T6868539.errors:I"); // 9: Fieldref - verify("T6868539", "Methodref +#[0-9]+\\.#[0-9]+ +// +T6868539.run:\\(\\)V"); // 10: Methodref - verify("T6868539", "InterfaceMethodref +#[0-9]+\\.#[0-9]+ +// +java/lang/Runnable\\.run:\\(\\)V"); + verify(output, "Integer +123456"); // 3: Integer + verify(output, "Float +123456.0f"); // 4: Float + verify(output, "Long +123456l"); // 5: Long + verify(output, "Double +123456.0d"); // 6: Double + verify(output, "Class +#[0-9]+ +// + T6868539"); // 7: Class + verify(output, "String +#[0-9]+ +// + not found"); // 8: String + verify(output, "Fieldref +#[0-9]+\\.#[0-9]+ +// +T6868539.errors:I"); // 9: Fieldref + verify(output, "Methodref +#[0-9]+\\.#[0-9]+ +// +T6868539.run:\\(\\)V"); // 10: Methodref + verify(output, "InterfaceMethodref +#[0-9]+\\.#[0-9]+ +// +java/lang/Runnable\\.run:\\(\\)V"); // 11: InterfaceMethodref - verify("T6868539", "NameAndType +#[0-9]+:#[0-9]+ +// +run:\\(\\)V"); // 12: NameAndType + verify(output, "NameAndType +#[0-9]+:#[0-9]+ +// +run:\\(\\)V"); // 12: NameAndType if (errors > 0) throw new Error(errors + " found."); } - void verify(String className, String... expects) { - String output = javap(className); + void verify(String output, String... expects) { for (String expect: expects) { if (!output.matches("(?s).*" + expect + ".*")) error(expect + " not found"); diff -r 7ad86852c38a -r fd2579b80b83 test/tools/javap/T6980017.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javap/T6980017.java Fri Sep 24 16:43:08 2010 -0700 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2010, 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 6980017 + * @summary javap -XDdetail:source behaves badly if source not available. + */ + +import java.io.*; + +public class T6980017 { + public static void main(String... args) throws Exception { + new T6980017().run(); + } + + void run() throws Exception { + + String[] args = { + "-v", + "-XDdetails:source", + "java.lang.Object" + }; + + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + int rc = com.sun.tools.javap.Main.run(args, pw); + pw.close(); + if (rc != 0) + error("Unexpected exit code: " + rc); + + boolean foundBlankSourceLine = false; + boolean foundNoSourceLine = false; + for (String line: sw.toString().split("[\r\n]+")) { + System.err.println(line); + if (line.contains("Source code not available")) + foundNoSourceLine = true; + if (line.matches("\\s*\\( *[0-9]+\\)\\s*")) + foundBlankSourceLine = true; + } + + if (foundBlankSourceLine) + error("found blank source lines"); + + if (!foundNoSourceLine) + error("did not find \"Source code not available\" message"); + + if (errors > 0) + throw new Exception(errors + " errors occurred"); + } + + void error(String msg) { + System.err.println(msg); + errors++; + } + + int errors; +}