# HG changeset patch # User jjg # Date 1264810011 28800 # Node ID a132763160d72e62bd2db3d8851ddfd9e1205110 # Parent 0dc780b4fcf399b51590d5d452545ac44ac290bf 6919889: assorted position errors in compiler syntax trees Reviewed-by: darcy diff -r 0dc780b4fcf3 -r a132763160d7 langtools/src/share/classes/com/sun/tools/javac/code/Flags.java --- a/langtools/src/share/classes/com/sun/tools/javac/code/Flags.java Wed Jan 27 14:46:37 2010 -0800 +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Flags.java Fri Jan 29 16:06:51 2010 -0800 @@ -113,6 +113,7 @@ public static final int ENUM = 1<<14; public static final int StandardFlags = 0x0fff; + public static final int ModifierFlags = StandardFlags & ~INTERFACE; // Because the following access flags are overloaded with other // bit positions, we translate them when reading and writing class diff -r 0dc780b4fcf3 -r a132763160d7 langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java --- a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Wed Jan 27 14:46:37 2010 -0800 +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Fri Jan 29 16:06:51 2010 -0800 @@ -761,23 +761,28 @@ JCExpression[] odStack = newOdStack(); List savedOp = opStackSupply.elems; Token[] opStack = newOpStack(); + List savedPos = posStackSupply.elems; + int[] posStack = newPosStack(); // optimization, was odStack = new Tree[...]; opStack = new Tree[...]; int top = 0; odStack[0] = t; int startPos = S.pos(); Token topOp = ERROR; + int topOpPos = Position.NOPOS; while (prec(S.token()) >= minprec) { + posStack[top] = topOpPos; opStack[top] = topOp; top++; topOp = S.token(); - int pos = S.pos(); + topOpPos = S.pos(); S.nextToken(); - odStack[top] = topOp == INSTANCEOF ? parseType() : term3(); + odStack[top] = (topOp == INSTANCEOF) ? parseType() : term3(); while (top > 0 && prec(topOp) >= prec(S.token())) { - odStack[top-1] = makeOp(pos, topOp, odStack[top-1], + odStack[top-1] = makeOp(topOpPos, topOp, odStack[top-1], odStack[top]); top--; topOp = opStack[top]; + topOpPos = posStack[top]; } } assert top == 0; @@ -792,6 +797,7 @@ odStackSupply.elems = savedOd; // optimization opStackSupply.elems = savedOp; // optimization + posStackSupply.elems = savedPos; // optimization return t; } //where @@ -845,6 +851,7 @@ */ ListBuffer odStackSupply = new ListBuffer(); ListBuffer opStackSupply = new ListBuffer(); + ListBuffer posStackSupply = new ListBuffer(); private JCExpression[] newOdStack() { if (odStackSupply.elems == odStackSupply.last) @@ -862,6 +869,14 @@ return opStack; } + private int[] newPosStack() { + if (posStackSupply.elems == posStackSupply.last) + posStackSupply.append(new int[infixPrecedenceLevels + 1]); + int[] posStack = posStackSupply.elems.head; + posStackSupply.elems = posStackSupply.elems.tail; + return posStack; + } + /** Expression3 = PrefixOp Expression3 * | "(" Expr | TypeNoParams ")" Expression3 * | Primary {Selector} {PostfixOp} @@ -939,7 +954,7 @@ args.append(typeArgument()); } accept(GT); - t = F.at(pos1).TypeApply(t, args.toList()); + t = toP(F.at(pos1).TypeApply(t, args.toList())); checkGenerics(); while (S.token() == DOT) { S.nextToken(); @@ -950,7 +965,8 @@ t = bracketsOpt(toP(t)); } else if ((mode & EXPR) != 0) { mode = EXPR; - t = F.at(pos1).Binary(op, t, term2Rest(t1, TreeInfo.shiftPrec)); + JCExpression e = term2Rest(t1, TreeInfo.shiftPrec); + t = F.at(pos1).Binary(op, t, e); t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec))); } else { accept(GT); @@ -998,7 +1014,8 @@ case SUPER: if ((mode & EXPR) != 0) { mode = EXPR; - t = to(superSuffix(typeArgs, F.at(pos).Ident(names._super))); + t = to(F.at(pos).Ident(names._super)); + t = superSuffix(typeArgs, t); typeArgs = null; } else return illegal(); break; @@ -1380,13 +1397,15 @@ S.nextToken(); JCExpression result; if (S.token() == EXTENDS) { - TypeBoundKind t = to(F.at(S.pos()).TypeBoundKind(BoundKind.EXTENDS)); + TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.EXTENDS)); S.nextToken(); - result = F.at(pos).Wildcard(t, parseType()); + JCExpression bound = parseType(); + result = F.at(pos).Wildcard(t, bound); } else if (S.token() == SUPER) { - TypeBoundKind t = to(F.at(S.pos()).TypeBoundKind(BoundKind.SUPER)); + TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.SUPER)); S.nextToken(); - result = F.at(pos).Wildcard(t, parseType()); + JCExpression bound = parseType(); + result = F.at(pos).Wildcard(t, bound); } else if (S.token() == IDENTIFIER) { //error recovery reportSyntaxError(S.prevEndPos(), "expected3", @@ -1396,7 +1415,7 @@ JCIdent id = toP(F.at(S.pos()).Ident(ident())); result = F.at(pos).Erroneous(List.of(wc, id)); } else { - TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND); + TypeBoundKind t = toP(F.at(pos).TypeBoundKind(BoundKind.UNBOUND)); result = toP(F.at(pos).Wildcard(t, null)); } if (!annotations.isEmpty()) @@ -2117,14 +2136,21 @@ return modifiersOpt(null); } JCModifiers modifiersOpt(JCModifiers partial) { - long flags = (partial == null) ? 0 : partial.flags; + long flags; + ListBuffer annotations = new ListBuffer(); + int pos; + if (partial == null) { + flags = 0; + pos = S.pos(); + } else { + flags = partial.flags; + annotations.appendList(partial.annotations); + pos = partial.pos; + } if (S.deprecatedFlag()) { flags |= Flags.DEPRECATED; S.resetDeprecatedFlag(); } - ListBuffer annotations = new ListBuffer(); - if (partial != null) annotations.appendList(partial.annotations); - int pos = S.pos(); int lastPos = Position.NOPOS; loop: while (true) { @@ -2150,12 +2176,12 @@ if (flag == Flags.ANNOTATION) { checkAnnotations(); if (S.token() != INTERFACE) { - JCAnnotation ann = annotation(lastPos, AnnotationKind.DEFAULT_ANNO); - // if first modifier is an annotation, set pos to annotation's. - if (flags == 0 && annotations.isEmpty()) - pos = ann.pos; - annotations.append(ann); - lastPos = ann.pos; + JCAnnotation ann = annotation(lastPos, AnnotationKind.DEFAULT_ANNO); + // if first modifier is an annotation, set pos to annotation's. + if (flags == 0 && annotations.isEmpty()) + pos = ann.pos; + annotations.append(ann); + lastPos = ann.pos; flag = 0; } } @@ -2169,7 +2195,7 @@ /* A modifiers tree with no modifier tokens or annotations * has no text position. */ - if (flags == 0 && annotations.isEmpty()) + if ((flags & Flags.ModifierFlags) == 0 && annotations.isEmpty()) pos = Position.NOPOS; JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList()); @@ -2226,7 +2252,8 @@ if (t1.getTag() == JCTree.IDENT && S.token() == EQ) { int pos = S.pos(); accept(EQ); - return toP(F.at(pos).Assign(t1, annotationValue())); + JCExpression v = annotationValue(); + return toP(F.at(pos).Assign(t1, v)); } else { return t1; } @@ -2543,10 +2570,9 @@ } List defs = enumBody(name); - JCModifiers newMods = - F.at(mods.pos).Modifiers(mods.flags|Flags.ENUM, mods.annotations); + mods.flags |= Flags.ENUM; JCClassDecl result = toP(F.at(pos). - ClassDef(newMods, name, List.nil(), + ClassDef(mods, name, List.nil(), null, implementing, defs)); attach(result, dc); return result; @@ -2695,16 +2721,8 @@ } else { pos = S.pos(); List typarams = typeParametersOpt(); - // Hack alert: if there are type arguments but no Modifiers, the start - // position will be lost unless we set the Modifiers position. There - // should be an AST node for type parameters (BugId 5005090). - if (typarams.length() > 0 && mods.pos == Position.NOPOS) { - mods.pos = pos; - } - List annosAfterParams = annotationsOpt(AnnotationKind.DEFAULT_ANNO); - Token token = S.token(); Name name = S.name(); pos = S.pos(); JCExpression type; @@ -2715,7 +2733,11 @@ type = to(F.at(pos).TypeIdent(TypeTags.VOID)); S.nextToken(); } else { - mods.annotations = mods.annotations.appendList(annosAfterParams); + if (annosAfterParams.nonEmpty()) { + mods.annotations = mods.annotations.appendList(annosAfterParams); + if (mods.pos == Position.NOPOS) + mods.pos = mods.annotations.head.pos; + } // method returns types are un-annotated types type = unannotatedType(); } @@ -2813,6 +2835,7 @@ } } } + JCMethodDecl result = toP(F.at(pos).MethodDef(mods, name, type, typarams, params, receiverAnnotations, thrown, diff -r 0dc780b4fcf3 -r a132763160d7 langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java --- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java Wed Jan 27 14:46:37 2010 -0800 +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java Fri Jan 29 16:06:51 2010 -0800 @@ -307,8 +307,18 @@ case(JCTree.POSTINC): case(JCTree.POSTDEC): return getStartPos(((JCUnary) tree).arg); - case(JCTree.ANNOTATED_TYPE): - return getStartPos(((JCAnnotatedType) tree).underlyingType); + case(JCTree.ANNOTATED_TYPE): { + JCAnnotatedType node = (JCAnnotatedType) tree; + if (node.annotations.nonEmpty()) + return getStartPos(node.annotations.head); + return getStartPos(node.underlyingType); + } + case(JCTree.NEWCLASS): { + JCNewClass node = (JCNewClass)tree; + if (node.encl != null) + return getStartPos(node.encl); + break; + } case(JCTree.VARDEF): { JCVariableDecl node = (JCVariableDecl)tree; if (node.mods.pos != Position.NOPOS) { @@ -406,6 +416,8 @@ return getEndPos(((JCUnary) tree).arg, endPositions); case(JCTree.WHILELOOP): return getEndPos(((JCWhileLoop) tree).body, endPositions); + case(JCTree.ANNOTATED_TYPE): + return getEndPos(((JCAnnotatedType) tree).underlyingType, endPositions); case(JCTree.ERRONEOUS): { JCErroneous node = (JCErroneous)tree; if (node.errs != null && node.errs.nonEmpty()) diff -r 0dc780b4fcf3 -r a132763160d7 langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java --- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java Wed Jan 27 14:46:37 2010 -0800 +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java Fri Jan 29 16:06:51 2010 -0800 @@ -480,7 +480,7 @@ public JCModifiers Modifiers(long flags, List annotations) { JCModifiers tree = new JCModifiers(flags, annotations); - boolean noFlags = (flags & Flags.StandardFlags) == 0; + boolean noFlags = (flags & Flags.ModifierFlags) == 0; tree.pos = (noFlags && annotations.isEmpty()) ? Position.NOPOS : pos; return tree; } diff -r 0dc780b4fcf3 -r a132763160d7 langtools/test/tools/javac/T6654037.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/T6654037.java Fri Jan 29 16:06:51 2010 -0800 @@ -0,0 +1,76 @@ +/* + * Copyright 2008-2010 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6654037 + * @summary JCTree.pos may be incorrect for BinaryTrees + */ + +import com.sun.source.tree.BinaryTree; +import com.sun.source.tree.ClassTree; +import com.sun.source.tree.CompilationUnitTree; +import com.sun.source.tree.MethodTree; +import com.sun.source.tree.VariableTree; +import com.sun.tools.javac.api.JavacTaskImpl; +import com.sun.tools.javac.tree.JCTree; +import java.net.URI; +import java.util.Arrays; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.SimpleJavaFileObject; +import javax.tools.ToolProvider; + +public class T6654037 { + + public static void main(String[] args) throws Exception { + final String bootPath = System.getProperty("sun.boot.class.path"); //NOI18N + final JavaCompiler tool = ToolProvider.getSystemJavaCompiler(); + assert tool != null; + + String code = "package test; public class Test {private void test() {Object o = null; boolean b = o != null && o instanceof String;} private Test() {}}"; + + JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, Arrays.asList("-bootclasspath", bootPath, "-Xjcov"), null, Arrays.asList(new MyFileObject(code))); + CompilationUnitTree cut = ct.parse().iterator().next(); + ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); + MethodTree method = (MethodTree) clazz.getMembers().get(0); + VariableTree condSt = (VariableTree) method.getBody().getStatements().get(1); + BinaryTree cond = (BinaryTree) condSt.getInitializer(); + JCTree condJC = (JCTree) cond; + + if (condJC.pos != 93) + throw new IllegalStateException("Unexpected position=" + condJC.pos); + } + + static class MyFileObject extends SimpleJavaFileObject { + private String text; + public MyFileObject(String text) { + super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); + this.text = text; + } + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return text; + } + } +} diff -r 0dc780b4fcf3 -r a132763160d7 langtools/test/tools/javac/generics/diamond/neg/Neg01.out --- a/langtools/test/tools/javac/generics/diamond/neg/Neg01.out Wed Jan 27 14:46:37 2010 -0800 +++ b/langtools/test/tools/javac/generics/diamond/neg/Neg01.out Fri Jan 29 16:06:51 2010 -0800 @@ -1,31 +1,31 @@ Neg01.java:18:15: compiler.err.not.within.bounds: java.lang.String Neg01.java:18:37: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg01, Neg01) -Neg01.java:19:25: compiler.err.not.within.bounds: ? extends java.lang.String +Neg01.java:19:15: compiler.err.not.within.bounds: ? extends java.lang.String Neg01.java:19:47: compiler.err.cant.apply.diamond: X, (compiler.misc.no.unique.maximal.instance.exists: X, java.lang.String,java.lang.Number) Neg01.java:20:23: compiler.err.cant.resolve.location.args: kindname.constructor, Neg01, , java.lang.String, kindname.class, Neg01 -Neg01.java:21:23: compiler.err.not.within.bounds: ? super java.lang.String +Neg01.java:21:15: compiler.err.not.within.bounds: ? super java.lang.String Neg01.java:21:45: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg01, Neg01) Neg01.java:23:15: compiler.err.not.within.bounds: java.lang.String Neg01.java:23:37: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg01, Neg01) -Neg01.java:24:25: compiler.err.not.within.bounds: ? extends java.lang.String +Neg01.java:24:15: compiler.err.not.within.bounds: ? extends java.lang.String Neg01.java:24:47: compiler.err.cant.apply.diamond: X, (compiler.misc.no.unique.maximal.instance.exists: X, java.lang.String,java.lang.Number) Neg01.java:25:23: compiler.err.cant.resolve.location.args: kindname.constructor, Neg01, , java.lang.String, kindname.class, Neg01 Neg01.java:25:38: compiler.err.cant.resolve.location.args: kindname.constructor, Neg01, , , kindname.class, Neg01 -Neg01.java:26:23: compiler.err.not.within.bounds: ? super java.lang.String +Neg01.java:26:15: compiler.err.not.within.bounds: ? super java.lang.String Neg01.java:26:45: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg01, Neg01) Neg01.java:28:15: compiler.err.not.within.bounds: java.lang.String Neg01.java:28:37: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg01, Neg01) -Neg01.java:29:25: compiler.err.not.within.bounds: ? extends java.lang.String +Neg01.java:29:15: compiler.err.not.within.bounds: ? extends java.lang.String Neg01.java:29:48: compiler.err.cant.apply.diamond: X, (compiler.misc.no.unique.maximal.instance.exists: X, java.lang.String,java.lang.Number) Neg01.java:30:24: compiler.err.cant.resolve.location.args: kindname.constructor, Neg01, , java.lang.String,java.lang.String, kindname.class, Neg01 Neg01.java:31:9: compiler.err.cant.resolve.location: kindname.class, Foo, , , kindname.class, Neg01 Neg01.java:31:35: compiler.err.cant.resolve.location.args: kindname.constructor, Neg01, , java.lang.String,java.lang.String, kindname.class, Neg01 Neg01.java:33:15: compiler.err.not.within.bounds: java.lang.String Neg01.java:33:38: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg01, Neg01) -Neg01.java:34:25: compiler.err.not.within.bounds: ? extends java.lang.String +Neg01.java:34:15: compiler.err.not.within.bounds: ? extends java.lang.String Neg01.java:34:48: compiler.err.cant.apply.diamond: X, (compiler.misc.no.unique.maximal.instance.exists: X, java.lang.String,java.lang.Number) Neg01.java:35:24: compiler.err.cant.resolve.location.args: kindname.constructor, Neg01, , java.lang.String,java.lang.String, kindname.class, Neg01 Neg01.java:35:43: compiler.err.cant.resolve.location.args: kindname.constructor, Neg01, , , kindname.class, Neg01 -Neg01.java:36:23: compiler.err.not.within.bounds: ? super java.lang.String +Neg01.java:36:15: compiler.err.not.within.bounds: ? super java.lang.String Neg01.java:36:46: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg01, Neg01) 30 errors diff -r 0dc780b4fcf3 -r a132763160d7 langtools/test/tools/javac/generics/diamond/neg/Neg02.out --- a/langtools/test/tools/javac/generics/diamond/neg/Neg02.out Wed Jan 27 14:46:37 2010 -0800 +++ b/langtools/test/tools/javac/generics/diamond/neg/Neg02.out Fri Jan 29 16:06:51 2010 -0800 @@ -1,61 +1,61 @@ Neg02.java:19:13: compiler.err.not.within.bounds: java.lang.String Neg02.java:19:33: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg02.Foo, Neg02.Foo) -Neg02.java:20:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg02.java:20:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg02.java:20:43: compiler.err.cant.apply.diamond: X, (compiler.misc.no.unique.maximal.instance.exists: X, java.lang.String,java.lang.Number) Neg02.java:21:21: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String, kindname.class, Neg02.Foo -Neg02.java:22:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg02.java:22:13: compiler.err.not.within.bounds: ? super java.lang.String Neg02.java:22:41: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg02.Foo, Neg02.Foo) Neg02.java:24:13: compiler.err.not.within.bounds: java.lang.String Neg02.java:24:33: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg02.Foo, Neg02.Foo) -Neg02.java:25:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg02.java:25:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg02.java:25:43: compiler.err.cant.apply.diamond: X, (compiler.misc.no.unique.maximal.instance.exists: X, java.lang.String,java.lang.Number) Neg02.java:26:21: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String, kindname.class, Neg02.Foo Neg02.java:26:34: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , , kindname.class, Neg02.Foo -Neg02.java:27:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg02.java:27:13: compiler.err.not.within.bounds: ? super java.lang.String Neg02.java:27:41: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg02.Foo, Neg02.Foo) Neg02.java:29:13: compiler.err.not.within.bounds: java.lang.String Neg02.java:29:33: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg02.Foo, Neg02.Foo) -Neg02.java:30:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg02.java:30:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg02.java:30:44: compiler.err.cant.apply.diamond: X, (compiler.misc.no.unique.maximal.instance.exists: X, java.lang.String,java.lang.Number) Neg02.java:31:22: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String,java.lang.String, kindname.class, Neg02.Foo -Neg02.java:32:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg02.java:32:13: compiler.err.not.within.bounds: ? super java.lang.String Neg02.java:32:42: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg02.Foo, Neg02.Foo) Neg02.java:34:13: compiler.err.not.within.bounds: java.lang.String Neg02.java:34:34: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg02.Foo, Neg02.Foo) -Neg02.java:35:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg02.java:35:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg02.java:35:44: compiler.err.cant.apply.diamond: X, (compiler.misc.no.unique.maximal.instance.exists: X, java.lang.String,java.lang.Number) Neg02.java:36:22: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String,java.lang.String, kindname.class, Neg02.Foo Neg02.java:36:39: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , , kindname.class, Neg02.Foo -Neg02.java:37:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg02.java:37:13: compiler.err.not.within.bounds: ? super java.lang.String Neg02.java:37:42: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg02.Foo, Neg02.Foo) Neg02.java:41:13: compiler.err.not.within.bounds: java.lang.String Neg02.java:41:39: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg02.Foo, Neg02.Foo) -Neg02.java:42:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg02.java:42:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg02.java:42:49: compiler.err.cant.apply.diamond: X, (compiler.misc.no.unique.maximal.instance.exists: X, java.lang.String,java.lang.Number) Neg02.java:43:21: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String, kindname.class, Neg02.Foo -Neg02.java:44:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg02.java:44:13: compiler.err.not.within.bounds: ? super java.lang.String Neg02.java:44:47: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg02.Foo, Neg02.Foo) Neg02.java:46:13: compiler.err.not.within.bounds: java.lang.String Neg02.java:46:39: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg02.Foo, Neg02.Foo) -Neg02.java:47:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg02.java:47:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg02.java:47:49: compiler.err.cant.apply.diamond: X, (compiler.misc.no.unique.maximal.instance.exists: X, java.lang.String,java.lang.Number) Neg02.java:48:21: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String, kindname.class, Neg02.Foo Neg02.java:48:40: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , , kindname.class, Neg02.Foo -Neg02.java:49:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg02.java:49:13: compiler.err.not.within.bounds: ? super java.lang.String Neg02.java:49:47: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg02.Foo, Neg02.Foo) Neg02.java:51:13: compiler.err.not.within.bounds: java.lang.String Neg02.java:51:39: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg02.Foo, Neg02.Foo) -Neg02.java:52:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg02.java:52:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg02.java:52:50: compiler.err.cant.apply.diamond: X, (compiler.misc.no.unique.maximal.instance.exists: X, java.lang.String,java.lang.Number) Neg02.java:53:22: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String,java.lang.String, kindname.class, Neg02.Foo -Neg02.java:54:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg02.java:54:13: compiler.err.not.within.bounds: ? super java.lang.String Neg02.java:54:48: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg02.Foo, Neg02.Foo) Neg02.java:56:13: compiler.err.not.within.bounds: java.lang.String Neg02.java:56:40: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg02.Foo, Neg02.Foo) -Neg02.java:57:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg02.java:57:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg02.java:57:50: compiler.err.cant.apply.diamond: X, (compiler.misc.no.unique.maximal.instance.exists: X, java.lang.String,java.lang.Number) Neg02.java:58:22: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String,java.lang.String, kindname.class, Neg02.Foo Neg02.java:58:45: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , , kindname.class, Neg02.Foo -Neg02.java:59:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg02.java:59:13: compiler.err.not.within.bounds: ? super java.lang.String Neg02.java:59:48: compiler.err.cant.apply.diamond: X, (compiler.misc.no.conforming.instance.exists: X, Neg02.Foo, Neg02.Foo) 60 errors diff -r 0dc780b4fcf3 -r a132763160d7 langtools/test/tools/javac/generics/diamond/neg/Neg03.out --- a/langtools/test/tools/javac/generics/diamond/neg/Neg03.out Wed Jan 27 14:46:37 2010 -0800 +++ b/langtools/test/tools/javac/generics/diamond/neg/Neg03.out Fri Jan 29 16:06:51 2010 -0800 @@ -1,91 +1,91 @@ Neg03.java:19:13: compiler.err.not.within.bounds: java.lang.String Neg03.java:19:33: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) -Neg03.java:20:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg03.java:20:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg03.java:20:43: compiler.err.cant.apply.diamond: V, (compiler.misc.no.unique.maximal.instance.exists: V, java.lang.String,java.lang.Number) Neg03.java:21:21: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String, kindname.class, Neg03.Foo -Neg03.java:22:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg03.java:22:13: compiler.err.not.within.bounds: ? super java.lang.String Neg03.java:22:41: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) Neg03.java:24:13: compiler.err.not.within.bounds: java.lang.String Neg03.java:24:33: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) -Neg03.java:25:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg03.java:25:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg03.java:25:43: compiler.err.cant.apply.diamond: V, (compiler.misc.no.unique.maximal.instance.exists: V, java.lang.String,java.lang.Number) Neg03.java:26:21: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String, kindname.class, Neg03.Foo Neg03.java:26:34: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , , kindname.class, Neg03.Foo -Neg03.java:27:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg03.java:27:13: compiler.err.not.within.bounds: ? super java.lang.String Neg03.java:27:41: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) Neg03.java:29:13: compiler.err.not.within.bounds: java.lang.String Neg03.java:29:33: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) -Neg03.java:30:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg03.java:30:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg03.java:30:44: compiler.err.cant.apply.diamond: V, (compiler.misc.no.unique.maximal.instance.exists: V, java.lang.String,java.lang.Number) Neg03.java:31:22: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String,java.lang.String, kindname.class, Neg03.Foo -Neg03.java:32:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg03.java:32:13: compiler.err.not.within.bounds: ? super java.lang.String Neg03.java:32:42: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) Neg03.java:34:13: compiler.err.not.within.bounds: java.lang.String Neg03.java:34:34: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) -Neg03.java:35:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg03.java:35:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg03.java:35:44: compiler.err.cant.apply.diamond: V, (compiler.misc.no.unique.maximal.instance.exists: V, java.lang.String,java.lang.Number) Neg03.java:36:22: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String,java.lang.String, kindname.class, Neg03.Foo Neg03.java:36:39: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , , kindname.class, Neg03.Foo -Neg03.java:37:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg03.java:37:13: compiler.err.not.within.bounds: ? super java.lang.String Neg03.java:37:42: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) Neg03.java:41:13: compiler.err.not.within.bounds: java.lang.String Neg03.java:41:42: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) -Neg03.java:42:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg03.java:42:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg03.java:42:52: compiler.err.cant.apply.diamond: V, (compiler.misc.no.unique.maximal.instance.exists: V, java.lang.String,java.lang.Number) Neg03.java:43:21: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String, kindname.class, Neg03.Foo -Neg03.java:44:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg03.java:44:13: compiler.err.not.within.bounds: ? super java.lang.String Neg03.java:44:50: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) Neg03.java:46:13: compiler.err.not.within.bounds: java.lang.String Neg03.java:46:42: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) -Neg03.java:47:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg03.java:47:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg03.java:47:52: compiler.err.cant.apply.diamond: V, (compiler.misc.no.unique.maximal.instance.exists: V, java.lang.String,java.lang.Number) Neg03.java:48:21: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String, kindname.class, Neg03.Foo Neg03.java:48:43: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , , kindname.class, Neg03.Foo -Neg03.java:49:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg03.java:49:13: compiler.err.not.within.bounds: ? super java.lang.String Neg03.java:49:50: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) Neg03.java:51:13: compiler.err.not.within.bounds: java.lang.String Neg03.java:51:42: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) -Neg03.java:52:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg03.java:52:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg03.java:52:53: compiler.err.cant.apply.diamond: V, (compiler.misc.no.unique.maximal.instance.exists: V, java.lang.String,java.lang.Number) Neg03.java:53:22: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String,java.lang.String, kindname.class, Neg03.Foo -Neg03.java:54:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg03.java:54:13: compiler.err.not.within.bounds: ? super java.lang.String Neg03.java:54:51: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) Neg03.java:56:13: compiler.err.not.within.bounds: java.lang.String Neg03.java:56:43: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) -Neg03.java:57:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg03.java:57:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg03.java:57:53: compiler.err.cant.apply.diamond: V, (compiler.misc.no.unique.maximal.instance.exists: V, java.lang.String,java.lang.Number) Neg03.java:58:22: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String,java.lang.String, kindname.class, Neg03.Foo Neg03.java:58:48: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , , kindname.class, Neg03.Foo -Neg03.java:59:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg03.java:59:13: compiler.err.not.within.bounds: ? super java.lang.String Neg03.java:59:51: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) Neg03.java:63:13: compiler.err.not.within.bounds: java.lang.String Neg03.java:63:28: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) -Neg03.java:64:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg03.java:64:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg03.java:64:38: compiler.err.cant.apply.diamond: V, (compiler.misc.no.unique.maximal.instance.exists: V, java.lang.String,java.lang.Number) Neg03.java:65:23: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String, kindname.class, Neg03.Foo -Neg03.java:66:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg03.java:66:13: compiler.err.not.within.bounds: ? super java.lang.String Neg03.java:66:36: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) Neg03.java:68:13: compiler.err.not.within.bounds: java.lang.String Neg03.java:68:28: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) -Neg03.java:69:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg03.java:69:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg03.java:69:38: compiler.err.cant.apply.diamond: V, (compiler.misc.no.unique.maximal.instance.exists: V, java.lang.String,java.lang.Number) Neg03.java:70:23: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String, kindname.class, Neg03.Foo Neg03.java:70:36: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , , kindname.class, Neg03.Foo -Neg03.java:71:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg03.java:71:13: compiler.err.not.within.bounds: ? super java.lang.String Neg03.java:71:36: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) Neg03.java:73:13: compiler.err.not.within.bounds: java.lang.String Neg03.java:73:28: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) -Neg03.java:74:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg03.java:74:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg03.java:74:39: compiler.err.cant.apply.diamond: V, (compiler.misc.no.unique.maximal.instance.exists: V, java.lang.String,java.lang.Number) Neg03.java:75:24: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String,java.lang.String, kindname.class, Neg03.Foo -Neg03.java:76:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg03.java:76:13: compiler.err.not.within.bounds: ? super java.lang.String Neg03.java:76:37: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) Neg03.java:78:13: compiler.err.not.within.bounds: java.lang.String Neg03.java:78:29: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) -Neg03.java:79:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg03.java:79:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg03.java:79:39: compiler.err.cant.apply.diamond: V, (compiler.misc.no.unique.maximal.instance.exists: V, java.lang.String,java.lang.Number) Neg03.java:80:24: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String,java.lang.String, kindname.class, Neg03.Foo Neg03.java:80:41: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , , kindname.class, Neg03.Foo -Neg03.java:81:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg03.java:81:13: compiler.err.not.within.bounds: ? super java.lang.String Neg03.java:81:37: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Neg03.Foo, Neg03.Foo) 90 errors diff -r 0dc780b4fcf3 -r a132763160d7 langtools/test/tools/javac/generics/diamond/neg/Neg04.out --- a/langtools/test/tools/javac/generics/diamond/neg/Neg04.out Wed Jan 27 14:46:37 2010 -0800 +++ b/langtools/test/tools/javac/generics/diamond/neg/Neg04.out Fri Jan 29 16:06:51 2010 -0800 @@ -1,31 +1,31 @@ Neg04.java:18:13: compiler.err.not.within.bounds: java.lang.String Neg04.java:18:33: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Foo, Foo) -Neg04.java:19:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg04.java:19:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg04.java:19:43: compiler.err.cant.apply.diamond: V, (compiler.misc.no.unique.maximal.instance.exists: V, java.lang.String,java.lang.Number) Neg04.java:20:21: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String, kindname.class, Foo -Neg04.java:21:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg04.java:21:13: compiler.err.not.within.bounds: ? super java.lang.String Neg04.java:21:41: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Foo, Foo) Neg04.java:23:13: compiler.err.not.within.bounds: java.lang.String Neg04.java:23:33: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Foo, Foo) -Neg04.java:24:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg04.java:24:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg04.java:24:43: compiler.err.cant.apply.diamond: V, (compiler.misc.no.unique.maximal.instance.exists: V, java.lang.String,java.lang.Number) Neg04.java:25:21: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String, kindname.class, Foo Neg04.java:25:34: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , , kindname.class, Foo -Neg04.java:26:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg04.java:26:13: compiler.err.not.within.bounds: ? super java.lang.String Neg04.java:26:41: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Foo, Foo) Neg04.java:28:13: compiler.err.not.within.bounds: java.lang.String Neg04.java:28:33: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Foo, Foo) -Neg04.java:29:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg04.java:29:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg04.java:29:44: compiler.err.cant.apply.diamond: V, (compiler.misc.no.unique.maximal.instance.exists: V, java.lang.String,java.lang.Number) Neg04.java:30:22: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String,java.lang.String, kindname.class, Foo -Neg04.java:31:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg04.java:31:13: compiler.err.not.within.bounds: ? super java.lang.String Neg04.java:31:42: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Foo, Foo) Neg04.java:33:13: compiler.err.not.within.bounds: java.lang.String Neg04.java:33:34: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Foo, Foo) -Neg04.java:34:23: compiler.err.not.within.bounds: ? extends java.lang.String +Neg04.java:34:13: compiler.err.not.within.bounds: ? extends java.lang.String Neg04.java:34:44: compiler.err.cant.apply.diamond: V, (compiler.misc.no.unique.maximal.instance.exists: V, java.lang.String,java.lang.Number) Neg04.java:35:22: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , java.lang.String,java.lang.String, kindname.class, Foo Neg04.java:35:39: compiler.err.cant.resolve.location.args: kindname.constructor, Foo, , , kindname.class, Foo -Neg04.java:36:21: compiler.err.not.within.bounds: ? super java.lang.String +Neg04.java:36:13: compiler.err.not.within.bounds: ? super java.lang.String Neg04.java:36:42: compiler.err.cant.apply.diamond: V, (compiler.misc.no.conforming.instance.exists: V, Foo, Foo) 30 errors diff -r 0dc780b4fcf3 -r a132763160d7 langtools/test/tools/javac/treepostests/TreePosTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/treepostests/TreePosTest.java Fri Jan 29 16:06:51 2010 -0800 @@ -0,0 +1,752 @@ +/* + * Copyright 2010 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +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 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.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +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 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.tools.javac.api.JavacTool; +import com.sun.tools.javac.code.Flags; +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; +import com.sun.tools.javac.tree.JCTree.JCNewClass; +import com.sun.tools.javac.tree.JCTree.JCVariableDecl; +import com.sun.tools.javac.tree.TreeInfo; +import com.sun.tools.javac.tree.TreeScanner; + +import static com.sun.tools.javac.util.Position.NOPOS; + +/** + * 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 6919889 + * @summary assorted position errors in compiler syntax trees + * @run main TreePosTest -q -r -ef ./tools/javac/typeAnnotations . + */ +public class TreePosTest { + /** + * 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 TreePosTest().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("-r")) { + if (excludeFiles.size() > 0) + throw new Error("-r must be used before -ef"); + 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 (gui || errors == 0); + } + + /** + * Print command line help. + * @param out output stream + */ + void usage(PrintStream out) { + out.println("Usage:"); + out.println(" java TreePosTest options... files..."); + out.println(""); + out.println("where options include:"); + out.println("-gui Display returns in a GUI viewer"); + out.println("-q Quiet: don't report on inapplicable files"); + 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(""); + 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++; + PosTester p = new PosTester(); + p.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(); + Charset cs = (encoding == null ? null : Charset.forName(encoding)); + 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++; + } + + /** 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; + /** Flag: show errors in GUI viewer. */ + boolean gui; + /** Option: encoding for test files. */ + String encoding; + /** The GUI viewer for errors. */ + Viewer viewer; + /** 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(); + /** Table of printable names for tree tag values. */ + TagNames tagNames = new TagNames(); + + /** + * Main class for testing assertions concerning tree positions for tree nodes. + */ + private class PosTester extends TreeScanner { + void test(JCCompilationUnit tree) { + sourcefile = tree.sourcefile; + endPosTable = tree.endPositions; + encl = new Info(); + tree.accept(this); + } + + @Override + public void scan(JCTree tree) { + if (tree == null) + return; + + Info self = new Info(tree, endPosTable); + if (check(self)) { + // Modifiers nodes are present throughout the tree even where + // there is no corresponding source text. + // Redundant semicolons in a class definition can cause empty + // initializer blocks with no positions. + if ((self.tag == JCTree.MODIFIERS || self.tag == JCTree.BLOCK) + && self.pos == NOPOS) { + // If pos is NOPOS, so should be the start and end positions + check("start == NOPOS", encl, self, self.start == NOPOS); + check("end == NOPOS", encl, self, self.end == NOPOS); + } else { + // For this node, start , pos, and endpos should be all defined + check("start != NOPOS", encl, self, self.start != NOPOS); + check("pos != NOPOS", encl, self, self.pos != NOPOS); + check("end != NOPOS", encl, self, self.end != NOPOS); + // The following should normally be ordered + // encl.start <= start <= pos <= end <= encl.end + // In addition, the position of the enclosing node should be + // within this node. + // The primary exceptions are for array type nodes, because of the + // need to support legacy syntax: + // e.g. int a[]; int[] b[]; int f()[] { return null; } + // and because of inconsistent nesting of left and right of + // array declarations: + // e.g. int[][] a = new int[2][]; + check("encl.start <= start", encl, self, encl.start <= self.start); + check("start <= pos", encl, self, self.start <= self.pos); + if (!(self.tag == JCTree.TYPEARRAY + && (encl.tag == JCTree.VARDEF || encl.tag == JCTree.TYPEARRAY))) { + check("encl.pos <= start || end <= encl.pos", + encl, self, encl.pos <= self.start || self.end <= encl.pos); + } + check("pos <= end", encl, self, self.pos <= self.end); + if (!(self.tag == JCTree.TYPEARRAY && encl.tag == JCTree.TYPEARRAY)) { + check("end <= encl.end", encl, self, self.end <= encl.end); + } + } + } + + Info prevEncl = encl; + encl = self; + tree.accept(this); + encl = prevEncl; + } + + @Override + public void visitVarDef(JCVariableDecl tree) { + // enum member declarations are desugared in the parser and have + // ill-defined semantics for tree positions, so for now, we + // skip the synthesized bits and just check parts which came from + // the original source text + if ((tree.mods.flags & Flags.ENUM) != 0) { + scan(tree.mods); + if (tree.init != null) { + if (tree.init.getTag() == JCTree.NEWCLASS) { + JCNewClass init = (JCNewClass) tree.init; + if (init.args != null && init.args.nonEmpty()) { + scan(init.args); + } + if (init.def != null && init.def.defs != null) { + scan(init.def.defs); + } + } + } + } else + super.visitVarDef(tree); + } + + boolean check(Info x) { + return tags.size() == 0 || tags.contains(tagNames.get(x.tag)); + } + + void check(String label, Info encl, Info self, boolean ok) { + if (!ok) { + if (gui) { + if (viewer == null) + viewer = new Viewer(); + viewer.addEntry(sourcefile, label, encl, self); + } + + String s = self.tree.toString(); + String msg = sourcefile.getName() + ": " + label + ": " + + "encl:" + encl + " this:" + self + "\n" + + s.substring(0, Math.min(80, s.length())).replaceAll("[\r\n]+", " "); + error(msg); + } + } + + 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 tagNames.get(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 TagNames { + String get(int tag) { + if (map == null) { + map = 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 { + map.put(f.getInt(null), f.getName()); + } catch (IllegalAccessException e) { + } + } + } + } + } + String name = map.get(tag); + return (name == null) ? "??" : name; + } + + private Map map; + } + + /** + * 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; + } + + /** + * 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(tagNames.get(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; + } + } +} +