Mercurial > hg > openjdk > jdk8u > langtools
changeset 1153:ab1b1cc78577 jdk8-b18
Merge
author | katleman |
---|---|
date | Thu, 15 Dec 2011 15:57:51 -0800 |
parents | 29a512337b79 (current diff) 55a49c399603 (diff) |
children | 3c71fcc22b99 ab2a880cc23b |
files | .hgtags test/tools/javac/parser/netbeans/JavacParserTest.java |
diffstat | 34 files changed, 2296 insertions(+), 835 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Thu Dec 15 15:47:47 2011 -0800 +++ b/.hgtags Thu Dec 15 15:57:51 2011 -0800 @@ -137,4 +137,5 @@ ae25163501bc7477cd907e26a006a6f1b05fdb6d jdk8-b13 58f1325d72b2bacc901f5189ee5e4e81e81ea657 jdk8-b14 07599bd780cab1f40da7915e1dc6774629b0cf8c jdk8-b15 +1cbe86c11ba69521875c0b0357d7540781eb334d jdk8-b17 ec2c0973cc31e143cffc05ceb63d98fae76f97d4 jdk8-b16
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/source/tree/LambdaExpressionTree.java Thu Dec 15 15:57:51 2011 -0800 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.source.tree; + +import java.util.List; + +/** + * A tree node for a lambda expression. + * + * For example: + * <pre> + * ()->{} + * (List<String> ls)->ls.size() + * (x,y)-> { return x + y; } + * </pre> + */ +public interface LambdaExpressionTree extends ExpressionTree { + + /** + * Lambda expressions come in two forms: (i) expression lambdas, whose body + * is an expression, and (ii) statement lambdas, whose body is a block + */ + public enum BodyKind { + /** enum constant for expression lambdas */ + EXPRESSION, + /** enum constant for statement lambdas */ + STATEMENT; + } + + List<? extends VariableTree> getParameters(); + Tree getBody(); + BodyKind getBodyKind(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/source/tree/MemberReferenceTree.java Thu Dec 15 15:57:51 2011 -0800 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.source.tree; + +import java.util.List; + +import javax.lang.model.element.Name; + +/** + * A tree node for a member reference expression. + * + * For example: + * <pre> + * <em>expression</em> # <em>[ identifier | new ]</em> + * </pre> + * + * @see JSR 292 + */ +public interface MemberReferenceTree extends ExpressionTree { + + /** + * There are two kinds of member references: (i) method references and + * (ii) constructor references + */ + public enum ReferenceMode { + /** enum constant for method references */ + INVOKE, + /** enum constant for constructor references */ + NEW + } + ReferenceMode getMode(); + ExpressionTree getQualifierExpression(); + Name getName(); + List<? extends ExpressionTree> getTypeArguments(); +}
--- a/src/share/classes/com/sun/source/tree/Tree.java Thu Dec 15 15:47:47 2011 -0800 +++ b/src/share/classes/com/sun/source/tree/Tree.java Thu Dec 15 15:57:51 2011 -0800 @@ -132,6 +132,11 @@ MEMBER_SELECT(MemberSelectTree.class), /** + * Used for instances of {@link MemberReferenceTree}. + */ + MEMBER_REFERENCE(MemberReferenceTree.class), + + /** * Used for instances of {@link ForLoopTree}. */ FOR_LOOP(ForLoopTree.class), @@ -187,6 +192,11 @@ NEW_CLASS(NewClassTree.class), /** + * Used for instances of {@link LambdaExpressionTree}. + */ + LAMBDA_EXPRESSION(LambdaExpressionTree.class), + + /** * Used for instances of {@link ParenthesizedTree}. */ PARENTHESIZED(ParenthesizedTree.class),
--- a/src/share/classes/com/sun/source/tree/TreeVisitor.java Thu Dec 15 15:47:47 2011 -0800 +++ b/src/share/classes/com/sun/source/tree/TreeVisitor.java Thu Dec 15 15:57:51 2011 -0800 @@ -85,9 +85,11 @@ R visitModifiers(ModifiersTree node, P p); R visitNewArray(NewArrayTree node, P p); R visitNewClass(NewClassTree node, P p); + R visitLambdaExpression(LambdaExpressionTree node, P p); R visitParenthesized(ParenthesizedTree node, P p); R visitReturn(ReturnTree node, P p); R visitMemberSelect(MemberSelectTree node, P p); + R visitMemberReference(MemberReferenceTree node, P p); R visitEmptyStatement(EmptyStatementTree node, P p); R visitSwitch(SwitchTree node, P p); R visitSynchronized(SynchronizedTree node, P p);
--- a/src/share/classes/com/sun/source/util/SimpleTreeVisitor.java Thu Dec 15 15:47:47 2011 -0800 +++ b/src/share/classes/com/sun/source/util/SimpleTreeVisitor.java Thu Dec 15 15:57:51 2011 -0800 @@ -172,6 +172,10 @@ return defaultAction(node, p); } + public R visitLambdaExpression(LambdaExpressionTree node, P p) { + return defaultAction(node, p); + } + public R visitParenthesized(ParenthesizedTree node, P p) { return defaultAction(node, p); } @@ -208,6 +212,10 @@ return defaultAction(node, p); } + public R visitMemberReference(MemberReferenceTree node, P p) { + return defaultAction(node, p); + } + public R visitIdentifier(IdentifierTree node, P p) { return defaultAction(node, p); }
--- a/src/share/classes/com/sun/source/util/TreeScanner.java Thu Dec 15 15:47:47 2011 -0800 +++ b/src/share/classes/com/sun/source/util/TreeScanner.java Thu Dec 15 15:57:51 2011 -0800 @@ -285,6 +285,12 @@ return r; } + public R visitLambdaExpression(LambdaExpressionTree node, P p) { + R r = scan(node.getParameters(), p); + r = scanAndReduce(node.getBody(), p, r); + return r; + } + public R visitParenthesized(ParenthesizedTree node, P p) { return scan(node.getExpression(), p); } @@ -333,6 +339,12 @@ return scan(node.getExpression(), p); } + public R visitMemberReference(MemberReferenceTree node, P p) { + R r = scan(node.getQualifierExpression(), p); + r = scanAndReduce(node.getTypeArguments(), p, r); + return r; + } + public R visitIdentifier(IdentifierTree node, P p) { return null; }
--- a/src/share/classes/com/sun/tools/javac/code/Source.java Thu Dec 15 15:47:47 2011 -0800 +++ b/src/share/classes/com/sun/tools/javac/code/Source.java Thu Dec 15 15:57:51 2011 -0800 @@ -194,6 +194,12 @@ public boolean allowObjectToPrimitiveCast() { return compareTo(JDK1_7) >= 0; } + public boolean allowLambda() { + return compareTo(JDK1_8) >= 0; + } + public boolean allowMethodReferences() { + return compareTo(JDK1_8) >= 0; + } public static SourceVersion toSourceVersion(Source source) { switch(source) { case JDK1_2:
--- a/src/share/classes/com/sun/tools/javac/comp/Attr.java Thu Dec 15 15:47:47 2011 -0800 +++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java Thu Dec 15 15:57:51 2011 -0800 @@ -1975,6 +1975,16 @@ result = check(tree, owntype, VAL, pkind, pt); } + @Override + public void visitLambda(JCLambda that) { + throw new UnsupportedOperationException("Lambda expression not supported yet"); + } + + @Override + public void visitReference(JCMemberReference that) { + throw new UnsupportedOperationException("Member references not supported yet"); + } + public void visitParens(JCParens tree) { Type owntype = attribTree(tree.expr, env, pkind, pt); result = check(tree, owntype, pkind, pkind, pt);
--- a/src/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java Thu Dec 15 15:47:47 2011 -0800 +++ b/src/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java Thu Dec 15 15:57:51 2011 -0800 @@ -637,6 +637,10 @@ lexError(pos, "unclosed.str.lit"); } break loop; + case '#': + reader.scanChar(); + tk = TokenKind.HASH; + break loop; default: if (isSpecial(reader.ch)) { scanOperator();
--- a/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Thu Dec 15 15:47:47 2011 -0800 +++ b/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Thu Dec 15 15:57:51 2011 -0800 @@ -27,6 +27,8 @@ import java.util.*; +import com.sun.source.tree.MemberReferenceTree.ReferenceMode; + import com.sun.tools.javac.code.*; import com.sun.tools.javac.parser.Tokens.*; import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle; @@ -110,6 +112,10 @@ this.allowDiamond = source.allowDiamond(); this.allowMulticatch = source.allowMulticatch(); this.allowStringFolding = fac.options.getBoolean("allowStringFolding", true); + this.allowLambda = source.allowLambda() && + fac.options.isSet("allowLambda"); + this.allowMethodReferences = source.allowMethodReferences() && + fac.options.isSet("allowMethodReferences"); this.keepDocComments = keepDocComments; docComments = keepDocComments ? new HashMap<JCTree,String>() : null; this.keepLineMap = keepLineMap; @@ -166,6 +172,14 @@ */ boolean allowStringFolding; + /** Switch: should we recognize lambda expressions? + */ + boolean allowLambda; + + /** Switch: should we allow method/constructor references? + */ + boolean allowMethodReferences; + /** Switch: should we keep docComments? */ boolean keepDocComments; @@ -203,6 +217,30 @@ token = S.token(); } + protected boolean peekToken(TokenKind tk) { + return S.token(1).kind == tk; + } + + protected boolean peekToken(TokenKind tk1, TokenKind tk2) { + return S.token(1).kind == tk1 && + S.token(2).kind == tk2; + } + + protected boolean peekToken(TokenKind tk1, TokenKind tk2, TokenKind tk3) { + return S.token(1).kind == tk1 && + S.token(2).kind == tk2 && + S.token(3).kind == tk3; + } + + protected boolean peekToken(TokenKind... kinds) { + for (int lookahead = 0 ; lookahead < kinds.length ; lookahead++) { + if (S.token(lookahead + 1).kind != kinds[lookahead]) { + return false; + } + } + return true; + } + /* ---------- error recovery -------------- */ private JCErroneous errorTree; @@ -749,7 +787,7 @@ top++; topOp = token; nextToken(); - odStack[top] = (topOp.kind == INSTANCEOF) ? parseType() : term3(); + odStack[top] = (topOp.kind == INSTANCEOF) ? parseType() : term3NoParams(); while (top > 0 && prec(topOp.kind) >= prec(token.kind)) { odStack[top-1] = makeOp(topOp.pos, topOp.kind, odStack[top-1], odStack[top]); @@ -849,7 +887,10 @@ * | [TypeArguments] THIS [Arguments] * | [TypeArguments] SUPER SuperSuffix * | NEW [TypeArguments] Creator + * | "(" Arguments ")" "->" ( Expression | Block ) + * | Ident "->" ( Expression | Block ) * | Ident { "." Ident } + * | Expression3 MemberReferenceSuffix * [ "[" ( "]" BracketsOpt "." CLASS | Expression "]" ) * | Arguments * | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator ) @@ -890,60 +931,87 @@ mode = EXPR; t = literal(names.hyphen, pos); } else { - t = term3(); + t = term3NoParams(); return F.at(pos).Unary(unoptag(tk), t); } } else return illegal(); break; case LPAREN: if (typeArgs == null && (mode & EXPR) != 0) { - nextToken(); - mode = EXPR | TYPE | NOPARAMS; - t = term3(); - if ((mode & TYPE) != 0 && token.kind == LT) { - // Could be a cast to a parameterized type - JCTree.Tag op = JCTree.Tag.LT; - int pos1 = token.pos; + if (peekToken(FINAL) || + peekToken(RPAREN) || + peekToken(IDENTIFIER, COMMA) || + peekToken(IDENTIFIER, RPAREN, ARROW)) { + //implicit n-ary lambda + t = lambdaExpressionOrStatement(true, peekToken(FINAL), pos); + break; + } else { nextToken(); - mode &= (EXPR | TYPE); - mode |= TYPEARG; - JCExpression t1 = term3(); - if ((mode & TYPE) != 0 && - (token.kind == COMMA || token.kind == GT)) { - mode = TYPE; - ListBuffer<JCExpression> args = new ListBuffer<JCExpression>(); - args.append(t1); - while (token.kind == COMMA) { + mode = EXPR | TYPE; + t = term3NoParams(); + if ((mode & TYPE) != 0 && token.kind == LT) { + // Could be a cast to a parameterized type + JCTree.Tag op = JCTree.Tag.LT; + int pos1 = token.pos; + nextToken(); + mode &= (EXPR | TYPE); + mode |= TYPEARG; + JCExpression t1 = term3(); + if ((mode & TYPE) != 0 && + (token.kind == COMMA || token.kind == GT)) { + mode = TYPE; + ListBuffer<JCExpression> args = new ListBuffer<JCExpression>(); + args.append(t1); + while (token.kind == COMMA) { + nextToken(); + args.append(typeArgument()); + } + accept(GT); + t = toP(F.at(pos1).TypeApply(t, args.toList())); + checkGenerics(); + mode = EXPR | TYPE; //could be a lambda or a method ref or a cast to a type + t = term3Rest(t, typeArgs); + if (token.kind == IDENTIFIER || token.kind == ELLIPSIS) { + //explicit lambda (w/ generic type) + mode = EXPR; + JCModifiers mods = F.at(token.pos).Modifiers(Flags.PARAMETER); + if (token.kind == ELLIPSIS) { + mods.flags = Flags.VARARGS; + t = to(F.at(token.pos).TypeArray(t)); + nextToken(); + } + t = lambdaExpressionOrStatement(variableDeclaratorId(mods, t), pos); + break; + } + } else { + Assert.check((mode & EXPR) != 0); + mode = EXPR; + JCExpression e = term2Rest(t1, TreeInfo.shiftPrec); + t = F.at(pos1).Binary(op, t, e); + t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec))); + } + } else if ((mode & TYPE) != 0 && + (token.kind == IDENTIFIER || token.kind == ELLIPSIS)) { + //explicit lambda (w/ non-generic type) + mode = EXPR; + JCModifiers mods = F.at(token.pos).Modifiers(Flags.PARAMETER); + if (token.kind == ELLIPSIS) { + mods.flags = Flags.VARARGS; + t = to(F.at(token.pos).TypeArray(t)); nextToken(); - args.append(typeArgument()); } - accept(GT); - t = toP(F.at(pos1).TypeApply(t, args.toList())); - checkGenerics(); - while (token.kind == DOT) { - nextToken(); - mode = TYPE; - t = toP(F.at(token.pos).Select(t, ident())); - t = typeArgumentsOpt(t); - } - t = bracketsOpt(toP(t)); - } else if ((mode & EXPR) != 0) { - mode = EXPR; - JCExpression e = term2Rest(t1, TreeInfo.shiftPrec); - t = F.at(pos1).Binary(op, t, e); + t = lambdaExpressionOrStatement(variableDeclaratorId(mods, t), pos); + break; + } else { t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec))); - } else { - accept(GT); } } - else { - t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec))); - } + accept(RPAREN); lastmode = mode; mode = EXPR; if ((lastmode & EXPR) == 0) { - JCExpression t1 = term3(); + JCExpression t1 = term3NoParams(); return F.at(pos).TypeCast(t, t1); } else if ((lastmode & TYPE) != 0) { switch (token.kind) { @@ -953,14 +1021,16 @@ case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL: case TRUE: case FALSE: case NULL: - case NEW: case IDENTIFIER: case ASSERT: case ENUM: + case NEW: case IDENTIFIER: case ASSERT: case ENUM: case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID: - JCExpression t1 = term3(); + JCExpression t1 = term3NoParams(); return F.at(pos).TypeCast(t, t1); } } - } else return illegal(); + } else { + return illegal(); + } t = toP(F.at(pos).Parens(t)); break; case THIS: @@ -1003,75 +1073,122 @@ break; case IDENTIFIER: case ASSERT: case ENUM: if (typeArgs != null) return illegal(); - t = toP(F.at(token.pos).Ident(ident())); - loop: while (true) { - pos = token.pos; - switch (token.kind) { - case LBRACKET: - nextToken(); - if (token.kind == RBRACKET) { + if ((mode & EXPR) != 0 && peekToken(ARROW)) { + t = lambdaExpressionOrStatement(false, false, pos); + } else { + t = toP(F.at(token.pos).Ident(ident())); + loop: while (true) { + pos = token.pos; + switch (token.kind) { + case LBRACKET: nextToken(); - t = bracketsOpt(t); - t = toP(F.at(pos).TypeArray(t)); - t = bracketsSuffix(t); - } else { + if (token.kind == RBRACKET) { + nextToken(); + t = bracketsOpt(t); + t = toP(F.at(pos).TypeArray(t)); + t = bracketsSuffix(t); + } else { + if ((mode & EXPR) != 0) { + mode = EXPR; + JCExpression t1 = term(); + t = to(F.at(pos).Indexed(t, t1)); + } + accept(RBRACKET); + } + break loop; + case LPAREN: if ((mode & EXPR) != 0) { mode = EXPR; - JCExpression t1 = term(); - t = to(F.at(pos).Indexed(t, t1)); + t = arguments(typeArgs, t); + typeArgs = null; + } + break loop; + case DOT: + nextToken(); + int oldmode = mode; + mode &= ~NOPARAMS; + typeArgs = typeArgumentsOpt(EXPR); + mode = oldmode; + if ((mode & EXPR) != 0) { + switch (token.kind) { + case CLASS: + if (typeArgs != null) return illegal(); + mode = EXPR; + t = to(F.at(pos).Select(t, names._class)); + nextToken(); + break loop; + case THIS: + if (typeArgs != null) return illegal(); + mode = EXPR; + t = to(F.at(pos).Select(t, names._this)); + nextToken(); + break loop; + case SUPER: + mode = EXPR; + t = to(F.at(pos).Select(t, names._super)); + t = superSuffix(typeArgs, t); + typeArgs = null; + break loop; + case NEW: + if (typeArgs != null) return illegal(); + mode = EXPR; + int pos1 = token.pos; + nextToken(); + if (token.kind == LT) typeArgs = typeArguments(false); + t = innerCreator(pos1, typeArgs, t); + typeArgs = null; + break loop; + } } - accept(RBRACKET); - } - break loop; - case LPAREN: - if ((mode & EXPR) != 0) { - mode = EXPR; - t = arguments(typeArgs, t); - typeArgs = null; + // typeArgs saved for next loop iteration. + t = toP(F.at(pos).Select(t, ident())); + break; +// case LT: +// if ((mode & (TYPE | NOPARAMS)) == 0) { +// //could be an unbound method reference whose qualifier +// //is a generic type i.e. A<S>#m +// mode = EXPR | TYPE; +// JCTree.Tag op = JCTree.Tag.LT; +// int pos1 = token.pos; +// nextToken(); +// mode |= EXPR | TYPE | TYPEARG; +// JCExpression t1 = term3(); +// if ((mode & TYPE) != 0 && +// (token.kind == COMMA || token.kind == GT)) { +// mode = TYPE; +// ListBuffer<JCExpression> args = new ListBuffer<JCExpression>(); +// args.append(t1); +// while (token.kind == COMMA) { +// nextToken(); +// args.append(typeArgument()); +// } +// accept(GT); +// t = toP(F.at(pos1).TypeApply(t, args.toList())); +// checkGenerics(); +// while (token.kind == DOT) { +// nextToken(); +// mode = TYPE; +// t = toP(F.at(token.pos).Select(t, ident())); +// t = typeArgumentsOpt(t); +// } +// if (token.kind != HASH) { +// //method reference expected here +// t = illegal(); +// } +// mode = EXPR; +// break; +// } else if ((mode & EXPR) != 0) { +// //rollback - it was a binary expression +// mode = EXPR; +// JCExpression e = term2Rest(t1, TreeInfo.shiftPrec); +// t = F.at(pos1).Binary(op, t, e); +// t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec))); +// } +// } +// break loop; + default: + break loop; } - break loop; - case DOT: - nextToken(); - int oldmode = mode; - mode &= ~NOPARAMS; - typeArgs = typeArgumentsOpt(EXPR); - mode = oldmode; - if ((mode & EXPR) != 0) { - switch (token.kind) { - case CLASS: - if (typeArgs != null) return illegal(); - mode = EXPR; - t = to(F.at(pos).Select(t, names._class)); - nextToken(); - break loop; - case THIS: - if (typeArgs != null) return illegal(); - mode = EXPR; - t = to(F.at(pos).Select(t, names._this)); - nextToken(); - break loop; - case SUPER: - mode = EXPR; - t = to(F.at(pos).Select(t, names._super)); - t = superSuffix(typeArgs, t); - typeArgs = null; - break loop; - case NEW: - if (typeArgs != null) return illegal(); - mode = EXPR; - int pos1 = token.pos; - nextToken(); - if (token.kind == LT) typeArgs = typeArguments(false); - t = innerCreator(pos1, typeArgs, t); - typeArgs = null; - break loop; - } - } - // typeArgs saved for next loop iteration. - t = toP(F.at(pos).Select(t, ident())); - break; - default: - break loop; } } if (typeArgs != null) illegal(); @@ -1105,6 +1222,19 @@ default: return illegal(); } + return term3Rest(t, typeArgs); + } + + JCExpression term3NoParams() { + try { + mode |= NOPARAMS; + return term3(); + } finally { + mode &= ~NOPARAMS; + } + } + + JCExpression term3Rest(JCExpression t, List<JCExpression> typeArgs) { if (typeArgs != null) illegal(); while (true) { int pos1 = token.pos; @@ -1149,6 +1279,11 @@ t = argumentsOpt(typeArgs, typeArgumentsOpt(t)); typeArgs = null; } + } else if ((mode & EXPR) != 0 && token.kind == HASH) { + mode = EXPR; + if (typeArgs != null) return illegal(); + accept(HASH); + t = memberReferenceSuffix(pos1, t); } else { break; } @@ -1162,12 +1297,59 @@ return toP(t); } + JCExpression lambdaExpressionOrStatement(JCVariableDecl firstParam, int pos) { + ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>(); + params.append(firstParam); + JCVariableDecl lastParam = firstParam; + while ((lastParam.mods.flags & Flags.VARARGS) == 0 && token.kind == COMMA) { + nextToken(); + params.append(lastParam = formalParameter()); + } + accept(RPAREN); + return lambdaExpressionOrStatementRest(params.toList(), pos); + } + + JCExpression lambdaExpressionOrStatement(boolean hasParens, boolean explicitParams, int pos) { + List<JCVariableDecl> params = explicitParams ? + formalParameters() : + implicitParameters(hasParens); + + return lambdaExpressionOrStatementRest(params, pos); + } + + JCExpression lambdaExpressionOrStatementRest(List<JCVariableDecl> args, int pos) { + if (token.kind != ARROW) { + //better error recovery + return F.at(pos).Erroneous(args); + } + + checkLambda(); + accept(ARROW); + + return token.kind == LBRACE ? + lambdaStatement(args, pos, pos) : + lambdaExpression(args, pos); + } + + JCExpression lambdaStatement(List<JCVariableDecl> args, int pos, int pos2) { + JCBlock block = block(pos2, 0); + return toP(F.at(pos).Lambda(args, block)); + } + + JCExpression lambdaExpression(List<JCVariableDecl> args, int pos) { + JCTree expr = parseExpression(); + return toP(F.at(pos).Lambda(args, expr)); + } + /** SuperSuffix = Arguments | "." [TypeArguments] Ident [Arguments] */ JCExpression superSuffix(List<JCExpression> typeArgs, JCExpression t) { nextToken(); if (token.kind == LPAREN || typeArgs != null) { t = arguments(typeArgs, t); + } else if (token.kind == HASH) { + if (typeArgs != null) return illegal(); + t = memberReferenceSuffix(t); } else { int pos = token.pos; accept(DOT); @@ -1377,6 +1559,36 @@ return t; } + /** + * MemberReferenceSuffix = "#" [TypeArguments] Ident + * | "#" [TypeArguments] "new" + */ + JCExpression memberReferenceSuffix(JCExpression t) { + int pos1 = token.pos; + accept(HASH); + return memberReferenceSuffix(pos1, t); + } + + JCExpression memberReferenceSuffix(int pos1, JCExpression t) { + checkMethodReferences(); + mode = EXPR; + List<JCExpression> typeArgs = null; + if (token.kind == LT) { + typeArgs = typeArguments(false); + } + Name refName = null; + ReferenceMode refMode = null; + if (token.kind == NEW) { + refMode = ReferenceMode.NEW; + refName = names.init; + nextToken(); + } else { + refMode = ReferenceMode.INVOKE; + refName = ident(); + } + return toP(F.at(t.getStartPosition()).Reference(refMode, refName, t, typeArgs)); + } + /** Creator = Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest ) */ JCExpression creator(int newpos, List<JCExpression> typeArgs) { @@ -2392,7 +2604,7 @@ * @param mods The modifiers starting the class declaration * @param dc The documentation comment for the class, or null. */ - JCClassDecl classDeclaration(JCModifiers mods, String dc) { + protected JCClassDecl classDeclaration(JCModifiers mods, String dc) { int pos = token.pos; accept(CLASS); Name name = ident(); @@ -2421,7 +2633,7 @@ * @param mods The modifiers starting the interface declaration * @param dc The documentation comment for the interface, or null. */ - JCClassDecl interfaceDeclaration(JCModifiers mods, String dc) { + protected JCClassDecl interfaceDeclaration(JCModifiers mods, String dc) { int pos = token.pos; accept(INTERFACE); Name name = ident(); @@ -2444,7 +2656,7 @@ * @param mods The modifiers starting the enum declaration * @param dc The documentation comment for the enum, or null. */ - JCClassDecl enumDeclaration(JCModifiers mods, String dc) { + protected JCClassDecl enumDeclaration(JCModifiers mods, String dc) { int pos = token.pos; accept(ENUM); Name name = ident(); @@ -2666,7 +2878,7 @@ * ConstructorDeclaratorRest = * "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody */ - JCTree methodDeclaratorRest(int pos, + protected JCTree methodDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name, @@ -2779,6 +2991,24 @@ return params.toList(); } + List<JCVariableDecl> implicitParameters(boolean hasParens) { + if (hasParens) { + accept(LPAREN); + } + ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>(); + if (token.kind != RPAREN && token.kind != ARROW) { + params.append(implicitParameter()); + while (token.kind == COMMA) { + nextToken(); + params.append(implicitParameter()); + } + } + if (hasParens) { + accept(RPAREN); + } + return params.toList(); + } + JCModifiers optFinal(long flags) { JCModifiers mods = modifiersOpt(); checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED)); @@ -2801,6 +3031,11 @@ return variableDeclaratorId(mods, type); } + protected JCVariableDecl implicitParameter() { + JCModifiers mods = F.at(token.pos).Modifiers(Flags.PARAMETER); + return variableDeclaratorId(mods, null); + } + /* ---------- auxiliary methods -------------- */ void error(int pos, String key, Object ... args) { @@ -3024,6 +3259,18 @@ allowTWR = true; } } + void checkLambda() { + if (!allowLambda) { + log.error(token.pos, "lambda.not.supported.in.source", source.name); + allowLambda = true; + } + } + void checkMethodReferences() { + if (!allowMethodReferences) { + log.error(token.pos, "method.references.not.supported.in.source", source.name); + allowMethodReferences = true; + } + } /* * a functional source tree and end position mappings
--- a/src/share/classes/com/sun/tools/javac/parser/Lexer.java Thu Dec 15 15:47:47 2011 -0800 +++ b/src/share/classes/com/sun/tools/javac/parser/Lexer.java Thu Dec 15 15:57:51 2011 -0800 @@ -50,6 +50,11 @@ Token token(); /** + * Return token with given lookahead. + */ + Token token(int lookahead); + + /** * Return the last character position of the previous token. */ Token prevToken();
--- a/src/share/classes/com/sun/tools/javac/parser/Scanner.java Thu Dec 15 15:47:47 2011 -0800 +++ b/src/share/classes/com/sun/tools/javac/parser/Scanner.java Thu Dec 15 15:57:51 2011 -0800 @@ -26,8 +26,9 @@ package com.sun.tools.javac.parser; import java.nio.*; +import java.util.List; +import java.util.ArrayList; -import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.Position.LineMap; import com.sun.tools.javac.parser.JavaTokenizer.*; @@ -53,6 +54,10 @@ */ private Token prevToken; + /** Buffer of saved tokens (used during lookahead) + */ + private List<Token> savedTokens = new ArrayList<Token>(); + private JavaTokenizer tokenizer; /** * Create a scanner from the input array. This method might @@ -80,16 +85,35 @@ } public Token token() { - return token; + return token(0); } + public Token token(int lookahead) { + if (lookahead == 0) { + return token; + } else { + ensureLookahead(lookahead); + return savedTokens.get(lookahead - 1); + } + } + //where + private void ensureLookahead(int lookahead) { + for (int i = savedTokens.size() ; i < lookahead ; i ++) { + savedTokens.add(tokenizer.readToken()); + } + } + public Token prevToken() { return prevToken; } public void nextToken() { prevToken = token; - token = tokenizer.readToken(); + if (!savedTokens.isEmpty()) { + token = savedTokens.remove(0); + } else { + token = tokenizer.readToken(); + } } public Token split() {
--- a/src/share/classes/com/sun/tools/javac/parser/Tokens.java Thu Dec 15 15:47:47 2011 -0800 +++ b/src/share/classes/com/sun/tools/javac/parser/Tokens.java Thu Dec 15 15:57:51 2011 -0800 @@ -176,6 +176,8 @@ TRUE("true", Tag.NAMED), FALSE("false", Tag.NAMED), NULL("null", Tag.NAMED), + ARROW("->"), + HASH("#"), LPAREN("("), RPAREN(")"), LBRACE("{"),
--- a/src/share/classes/com/sun/tools/javac/resources/compiler.properties Thu Dec 15 15:47:47 2011 -0800 +++ b/src/share/classes/com/sun/tools/javac/resources/compiler.properties Thu Dec 15 15:57:51 2011 -0800 @@ -1945,6 +1945,16 @@ strings in switch are not supported in -source {0}\n\ (use -source 7 or higher to enable strings in switch) +# 0: string +compiler.err.lambda.not.supported.in.source=\ + lambda expressions are not supported in -source {0}\n\ + (use -source 8 or higher to enable lambda expressions) + +# 0: string +compiler.err.method.references.not.supported.in.source=\ + method references are not supported in -source {0}\n\ + (use -source 8 or higher to enable method references) + ######################################## # Diagnostics for verbose resolution # used by Resolve (debug only)
--- a/src/share/classes/com/sun/tools/javac/tree/JCTree.java Thu Dec 15 15:47:47 2011 -0800 +++ b/src/share/classes/com/sun/tools/javac/tree/JCTree.java Thu Dec 15 15:57:51 2011 -0800 @@ -41,6 +41,8 @@ import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.parser.EndPosTable; import com.sun.source.tree.*; +import com.sun.source.tree.LambdaExpressionTree.BodyKind; +import com.sun.source.tree.MemberReferenceTree.ReferenceMode; import static com.sun.tools.javac.code.BoundKind.*; import static com.sun.tools.javac.tree.JCTree.Tag.*; @@ -198,6 +200,10 @@ */ NEWARRAY, + /** Lambda expression, of type Lambda. + */ + LAMBDA, + /** Parenthesized subexpressions, of type Parens. */ PARENS, @@ -222,6 +228,10 @@ */ SELECT, + /** Member references, of type Reference. + */ + REFERENCE, + /** Simple identifiers, of type Ident. */ IDENT, @@ -1487,6 +1497,56 @@ } /** + * A lambda expression. + */ + public static class JCLambda extends JCExpression implements LambdaExpressionTree { + + public List<JCVariableDecl> params; + public JCTree body; + public Type targetType; + public boolean canCompleteNormally = true; + public List<Type> inferredThrownTypes; + + public JCLambda(List<JCVariableDecl> params, + JCTree body) { + this.params = params; + this.body = body; + } + @Override + public Tag getTag() { + return LAMBDA; + } + @Override + public void accept(Visitor v) { + v.visitLambda(this); + } + @Override + public <R, D> R accept(TreeVisitor<R, D> v, D d) { + return v.visitLambdaExpression(this, d); + } + public Kind getKind() { + return Kind.LAMBDA_EXPRESSION; + } + public JCTree getBody() { + return body; + } + public java.util.List<? extends VariableTree> getParameters() { + return params; + } + @Override + public JCLambda setType(Type type) { + super.setType(type); + return this; + } + @Override + public BodyKind getBodyKind() { + return body.hasTag(BLOCK) ? + BodyKind.STATEMENT : + BodyKind.EXPRESSION; + } + } + + /** * A parenthesized subexpression ( ... ) */ public static class JCParens extends JCExpression implements ParenthesizedTree { @@ -1747,6 +1807,46 @@ } /** + * Selects a member expression. + */ + public static class JCMemberReference extends JCExpression implements MemberReferenceTree { + public ReferenceMode mode; + public Name name; + public JCExpression expr; + public List<JCExpression> typeargs; + public Type targetType; + public Symbol sym; + + protected JCMemberReference(ReferenceMode mode, Name name, JCExpression expr, List<JCExpression> typeargs) { + this.mode = mode; + this.name = name; + this.expr = expr; + this.typeargs = typeargs; + } + @Override + public void accept(Visitor v) { v.visitReference(this); } + + public Kind getKind() { return Kind.MEMBER_REFERENCE; } + @Override + public ReferenceMode getMode() { return mode; } + @Override + public JCExpression getQualifierExpression() { return expr; } + @Override + public Name getName() { return name; } + @Override + public List<JCExpression> getTypeArguments() { return typeargs; } + + @Override + public <R,D> R accept(TreeVisitor<R,D> v, D d) { + return v.visitMemberReference(this, d); + } + @Override + public Tag getTag() { + return REFERENCE; + } + } + + /** * An identifier * @param idname the name * @param sym the symbol @@ -2271,6 +2371,7 @@ public void visitApply(JCMethodInvocation that) { visitTree(that); } public void visitNewClass(JCNewClass that) { visitTree(that); } public void visitNewArray(JCNewArray that) { visitTree(that); } + public void visitLambda(JCLambda that) { visitTree(that); } public void visitParens(JCParens that) { visitTree(that); } public void visitAssign(JCAssign that) { visitTree(that); } public void visitAssignop(JCAssignOp that) { visitTree(that); } @@ -2280,6 +2381,7 @@ public void visitTypeTest(JCInstanceOf that) { visitTree(that); } public void visitIndexed(JCArrayAccess that) { visitTree(that); } public void visitSelect(JCFieldAccess that) { visitTree(that); } + public void visitReference(JCMemberReference that) { visitTree(that); } public void visitIdent(JCIdent that) { visitTree(that); } public void visitLiteral(JCLiteral that) { visitTree(that); } public void visitTypeIdent(JCPrimitiveTypeTree that) { visitTree(that); }
--- a/src/share/classes/com/sun/tools/javac/tree/Pretty.java Thu Dec 15 15:47:47 2011 -0800 +++ b/src/share/classes/com/sun/tools/javac/tree/Pretty.java Thu Dec 15 15:57:51 2011 -0800 @@ -28,6 +28,8 @@ import java.io.*; import java.util.*; +import com.sun.source.tree.MemberReferenceTree.ReferenceMode; + import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.List; import com.sun.tools.javac.code.*; @@ -907,6 +909,17 @@ } } + public void visitLambda(JCLambda tree) { + try { + print("("); + printExprs(tree.params); + print(")->"); + printExpr(tree.body); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + public void visitParens(JCParens tree) { try { print("("); @@ -1052,6 +1065,21 @@ } } + public void visitReference(JCMemberReference tree) { + try { + printExpr(tree.expr); + print("#"); + if (tree.typeargs != null) { + print("<"); + printExprs(tree.typeargs); + print(">"); + } + print(tree.getMode() == ReferenceMode.INVOKE ? tree.name : "new"); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + public void visitIdent(JCIdent tree) { try { print(tree.name);
--- a/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java Thu Dec 15 15:47:47 2011 -0800 +++ b/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java Thu Dec 15 15:57:51 2011 -0800 @@ -271,6 +271,13 @@ return M.at(t.pos).NewClass(encl, typeargs, clazz, args, def); } + public JCTree visitLambdaExpression(LambdaExpressionTree node, P p) { + JCLambda t = (JCLambda) node; + List<JCVariableDecl> params = copy(t.params, p); + JCTree body = copy(t.body, p); + return M.at(t.pos).Lambda(params, body); + } + public JCTree visitParenthesized(ParenthesizedTree node, P p) { JCParens t = (JCParens) node; JCExpression expr = copy(t.expr, p); @@ -289,6 +296,13 @@ return M.at(t.pos).Select(selected, t.name); } + public JCTree visitMemberReference(MemberReferenceTree node, P p) { + JCMemberReference t = (JCMemberReference) node; + JCExpression expr = copy(t.expr, p); + List<JCExpression> typeargs = copy(t.typeargs, p); + return M.at(t.pos).Reference(t.mode, t.name, expr, typeargs); + } + public JCTree visitEmptyStatement(EmptyStatementTree node, P p) { JCSkip t = (JCSkip) node; return M.at(t.pos).Skip();
--- a/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java Thu Dec 15 15:47:47 2011 -0800 +++ b/src/share/classes/com/sun/tools/javac/tree/TreeInfo.java Thu Dec 15 15:57:51 2011 -0800 @@ -227,6 +227,34 @@ } } + /** + * Return true if the AST corresponds to a static select of the kind A.B + */ + public static boolean isStaticSelector(JCTree base, Names names) { + if (base == null) + return false; + switch (base.getTag()) { + case IDENT: + JCIdent id = (JCIdent)base; + return id.name != names._this && + id.name != names._super && + isStaticSym(base); + case SELECT: + return isStaticSym(base) && + isStaticSelector(((JCFieldAccess)base).selected, names); + case TYPEAPPLY: + return true; + default: + return false; + } + } + //where + private static boolean isStaticSym(JCTree tree) { + Symbol sym = symbol(tree); + return (sym.kind == Kinds.TYP || + sym.kind == Kinds.PCK); + } + /** Return true if a tree represents the null literal. */ public static boolean isNull(JCTree tree) { if (!tree.hasTag(LITERAL))
--- a/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java Thu Dec 15 15:47:47 2011 -0800 +++ b/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java Thu Dec 15 15:57:51 2011 -0800 @@ -351,6 +351,14 @@ return tree; } + public JCLambda Lambda(List<JCVariableDecl> params, + JCTree body) + { + JCLambda tree = new JCLambda(params, body); + tree.pos = pos; + return tree; + } + public JCParens Parens(JCExpression expr) { JCParens tree = new JCParens(expr); tree.pos = pos; @@ -405,6 +413,13 @@ return tree; } + public JCMemberReference Reference(JCMemberReference.ReferenceMode mode, Name name, + JCExpression expr, List<JCExpression> typeargs) { + JCMemberReference tree = new JCMemberReference(mode, name, expr, typeargs); + tree.pos = pos; + return tree; + } + public JCIdent Ident(Name name) { JCIdent tree = new JCIdent(name, null); tree.pos = pos;
--- a/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java Thu Dec 15 15:47:47 2011 -0800 +++ b/src/share/classes/com/sun/tools/javac/tree/TreeScanner.java Thu Dec 15 15:57:51 2011 -0800 @@ -212,6 +212,11 @@ scan(tree.elems); } + public void visitLambda(JCLambda tree) { + scan(tree.body); + scan(tree.params); + } + public void visitParens(JCParens tree) { scan(tree.expr); } @@ -254,6 +259,11 @@ scan(tree.selected); } + public void visitReference(JCMemberReference tree) { + scan(tree.expr); + scan(tree.typeargs); + } + public void visitIdent(JCIdent tree) { }
--- a/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java Thu Dec 15 15:47:47 2011 -0800 +++ b/src/share/classes/com/sun/tools/javac/tree/TreeTranslator.java Thu Dec 15 15:57:51 2011 -0800 @@ -282,6 +282,12 @@ result = tree; } + public void visitLambda(JCLambda tree) { + tree.params = translate(tree.params); + tree.body = translate(tree.body); + result = tree; + } + public void visitNewArray(JCNewArray tree) { tree.elemtype = translate(tree.elemtype); tree.dims = translate(tree.dims); @@ -340,6 +346,11 @@ result = tree; } + public void visitReference(JCMemberReference tree) { + tree.expr = translate(tree.expr); + result = tree; + } + public void visitIdent(JCIdent tree) { result = tree; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/T7120266.java Thu Dec 15 15:57:51 2011 -0800 @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7120266 + * @summary javac fails to compile hotspot code + * @compile T7120266.java + */ + +class T7120266 { + void test(int i, int len) { that(i < len, "oopmap"); } + void that(boolean b, String s) { }; +}
--- a/test/tools/javac/diags/examples/CatchWithoutTry.java Thu Dec 15 15:47:47 2011 -0800 +++ b/test/tools/javac/diags/examples/CatchWithoutTry.java Thu Dec 15 15:57:51 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,6 @@ // key: compiler.err.catch.without.try // key: compiler.err.expected -// key: compiler.err.not.stmt class CatchWithoutTry { void m() {
--- a/test/tools/javac/diags/examples/IllegalChar.java Thu Dec 15 15:47:47 2011 -0800 +++ b/test/tools/javac/diags/examples/IllegalChar.java Thu Dec 15 15:57:51 2011 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,5 +24,5 @@ // key: compiler.err.illegal.char class IllegalChar { - int i = #; + int i = `; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/diags/examples/LambdaNotSupported.java Thu Dec 15 15:57:51 2011 -0800 @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// key: compiler.err.lambda.not.supported.in.source +// options: -source 7 -Xlint:-options + +class LambdaNotSupported { + S s = ()->{}; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/diags/examples/MethodReferencesNotSupported.java Thu Dec 15 15:57:51 2011 -0800 @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// key: compiler.err.method.references.not.supported.in.source +// options: -source 7 -Xlint:-options + +class MethodReferencesNotSupported { + S s = A#foo; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/diags/examples/NotAStatement.java Thu Dec 15 15:57:51 2011 -0800 @@ -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. + */ + +// key: compiler.err.not.stmt + +class NotAStatement { + void m() { + x + 1; + } +}
--- a/test/tools/javac/generics/rare/6665356/T6665356.out Thu Dec 15 15:47:47 2011 -0800 +++ b/test/tools/javac/generics/rare/6665356/T6665356.out Thu Dec 15 15:57:51 2011 -0800 @@ -1,5 +1,5 @@ T6665356.java:17:37: compiler.err.improperly.formed.type.param.missing T6665356.java:18:40: compiler.err.improperly.formed.type.inner.raw.param -T6665356.java:26:23: compiler.err.improperly.formed.type.param.missing +T6665356.java:26:22: compiler.err.improperly.formed.type.param.missing T6665356.java:27:25: compiler.err.improperly.formed.type.inner.raw.param 4 errors
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/lambda/LambdaParserTest.java Thu Dec 15 15:57:51 2011 -0800 @@ -0,0 +1,276 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7115050 + * @summary Add parser support for lambda expressions + */ + +import com.sun.source.util.JavacTask; +import java.net.URI; +import java.util.Arrays; +import javax.tools.Diagnostic; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.SimpleJavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.ToolProvider; + +public class LambdaParserTest { + + static int checkCount = 0; + + enum LambdaKind { + NILARY_EXPR("()->x"), + NILARY_STMT("()->{ return x; }"), + ONEARY_SHORT_EXPR("x->x"), + ONEARY_SHORT_STMT("x->{ return x; }"), + ONEARY_EXPR("(#M1 #T1 x)->x"), + ONEARY_STMT("(#M1 #T1 x)->{ return x; }"), + TWOARY_EXPR("(#M1 #T1 x, #M2 #T2 y)->x"), + TWOARY_STMT("(#M1 #T1 x, #M2 #T2 y)->{ return x; }"); + + String lambdaTemplate; + + LambdaKind(String lambdaTemplate) { + this.lambdaTemplate = lambdaTemplate; + } + + String getLambdaString(LambdaParameterKind pk1, LambdaParameterKind pk2, + ModifierKind mk1, ModifierKind mk2) { + return lambdaTemplate.replaceAll("#M1", mk1.modifier) + .replaceAll("#M2", mk2.modifier) + .replaceAll("#T1", pk1.parameterType) + .replaceAll("#T2", pk2.parameterType); + } + + int arity() { + switch (this) { + case NILARY_EXPR: + case NILARY_STMT: return 0; + case ONEARY_SHORT_EXPR: + case ONEARY_SHORT_STMT: + case ONEARY_EXPR: + case ONEARY_STMT: return 1; + case TWOARY_EXPR: + case TWOARY_STMT: return 2; + default: throw new AssertionError("Invalid lambda kind " + this); + } + } + + boolean isShort() { + return this == ONEARY_SHORT_EXPR || + this == ONEARY_SHORT_STMT; + } + } + + enum LambdaParameterKind { + IMPLICIT(""), + EXPLIICT_SIMPLE("A"), + EXPLICIT_VARARGS("A..."), + EXPLICIT_GENERIC1("A<X>"), + EXPLICIT_GENERIC3("A<? extends X, ? super Y>"); + + String parameterType; + + LambdaParameterKind(String parameterType) { + this.parameterType = parameterType; + } + + boolean explicit() { + return this != IMPLICIT; + } + } + + enum ModifierKind { + NONE(""), + FINAL("final"), + PUBLIC("public"); + + String modifier; + + ModifierKind(String modifier) { + this.modifier = modifier; + } + + boolean compatibleWith(LambdaParameterKind pk) { + switch (this) { + case PUBLIC: return false; + case FINAL: return pk != LambdaParameterKind.IMPLICIT; + case NONE: return true; + default: throw new AssertionError("Invalid modifier kind " + this); + } + } + } + + enum ExprKind { + NONE("#L#S"), + SINGLE_PAREN1("(#L#S)"), + SINGLE_PAREN2("(#L)#S"), + DOUBLE_PAREN1("((#L#S))"), + DOUBLE_PAREN2("((#L)#S)"), + DOUBLE_PAREN3("((#L))#S"); + + String expressionTemplate; + + ExprKind(String expressionTemplate) { + this.expressionTemplate = expressionTemplate; + } + + String expressionString(LambdaParameterKind pk1, LambdaParameterKind pk2, + ModifierKind mk1, ModifierKind mk2, LambdaKind lk, SubExprKind sk) { + return expressionTemplate.replaceAll("#L", lk.getLambdaString(pk1, pk2, mk1, mk2)) + .replaceAll("#S", sk.subExpression); + } + } + + enum SubExprKind { + NONE(""), + SELECT_FIELD(".f"), + SELECT_METHOD(".f()"), + SELECT_NEW(".new Foo()"), + POSTINC("++"), + POSTDEC("--"); + + String subExpression; + + SubExprKind(String subExpression) { + this.subExpression = subExpression; + } + } + + public static void main(String... args) throws Exception { + + //create default shared JavaCompiler - reused across multiple compilations + JavaCompiler comp = ToolProvider.getSystemJavaCompiler(); + StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null); + + for (LambdaKind lk : LambdaKind.values()) { + for (LambdaParameterKind pk1 : LambdaParameterKind.values()) { + if (lk.arity() < 1 && pk1 != LambdaParameterKind.IMPLICIT) continue; + for (LambdaParameterKind pk2 : LambdaParameterKind.values()) { + if (lk.arity() < 2 && pk2 != LambdaParameterKind.IMPLICIT) continue; + for (ModifierKind mk1 : ModifierKind.values()) { + if (mk1 != ModifierKind.NONE && lk.isShort()) continue; + if (lk.arity() < 1 && mk1 != ModifierKind.NONE) continue; + for (ModifierKind mk2 : ModifierKind.values()) { + if (lk.arity() < 2 && mk2 != ModifierKind.NONE) continue; + for (SubExprKind sk : SubExprKind.values()) { + for (ExprKind ek : ExprKind.values()) { + new LambdaParserTest(pk1, pk2, mk1, mk2, lk, sk, ek) + .run(comp, fm); + } + } + } + } + } + } + } + System.out.println("Total check executed: " + checkCount); + } + + LambdaParameterKind pk1; + LambdaParameterKind pk2; + ModifierKind mk1; + ModifierKind mk2; + LambdaKind lk; + SubExprKind sk; + ExprKind ek; + JavaSource source; + DiagnosticChecker diagChecker; + + LambdaParserTest(LambdaParameterKind pk1, LambdaParameterKind pk2, ModifierKind mk1, + ModifierKind mk2, LambdaKind lk, SubExprKind sk, ExprKind ek) { + this.pk1 = pk1; + this.pk2 = pk2; + this.mk1 = mk1; + this.mk2 = mk2; + this.lk = lk; + this.sk = sk; + this.ek = ek; + this.source = new JavaSource(); + this.diagChecker = new DiagnosticChecker(); + } + + class JavaSource extends SimpleJavaFileObject { + + String template = "class Test {\n" + + " SAM s = #E;\n" + + "}"; + + String source; + + public JavaSource() { + super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); + source = template.replaceAll("#E", ek.expressionString(pk1, pk2, mk1, mk2, lk, sk)); + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return source; + } + } + + void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception { + JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker, + Arrays.asList("-XDallowLambda"), null, Arrays.asList(source)); + try { + ct.parse(); + } catch (Throwable ex) { + throw new AssertionError("Error thron when parsing the following source:\n" + source.getCharContent(true)); + } + check(); + } + + void check() { + checkCount++; + + boolean errorExpected = (lk.arity() > 0 && !mk1.compatibleWith(pk1)) || + (lk.arity() > 1 && !mk2.compatibleWith(pk2)); + + if (lk.arity() == 2 && + (pk1.explicit() != pk2.explicit() || + pk1 == LambdaParameterKind.EXPLICIT_VARARGS)) { + errorExpected = true; + } + + if (errorExpected != diagChecker.errorFound) { + throw new Error("invalid diagnostics for source:\n" + + source.getCharContent(true) + + "\nFound error: " + diagChecker.errorFound + + "\nExpected error: " + errorExpected); + } + } + + static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> { + + boolean errorFound; + + public void report(Diagnostic<? extends JavaFileObject> diagnostic) { + if (diagnostic.getKind() == Diagnostic.Kind.ERROR) { + errorFound = true; + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/lambda/MethodReferenceParserTest.java Thu Dec 15 15:57:51 2011 -0800 @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7115052 + * @ignore 7120266 + * @summary Add parser support for method references + */ + +import com.sun.source.util.JavacTask; +import java.net.URI; +import java.util.Arrays; +import javax.tools.Diagnostic; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.SimpleJavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.ToolProvider; + +public class MethodReferenceParserTest { + + static int checkCount = 0; + + enum ReferenceKind { + METHOD_REF("#Q##Gm"), + CONSTRUCTOR_REF("#Q##Gnew"), + ERR_SUPER("#Q##Gsuper"), + ERR_METH0("#Q##Gm()"), + ERR_METH1("#Q##Gm(X)"), + ERR_CONSTR0("#Q##Gnew()"), + ERR_CONSTR1("#Q##Gnew(X)"); + + String referenceTemplate; + + ReferenceKind(String referenceTemplate) { + this.referenceTemplate = referenceTemplate; + } + + String getReferenceString(QualifierKind qk, GenericKind gk) { + return referenceTemplate + .replaceAll("#Q", qk.qualifier) + .replaceAll("#G", gk.typeParameters); + } + + boolean erroneous() { + switch (this) { + case ERR_SUPER: + case ERR_METH0: + case ERR_METH1: + case ERR_CONSTR0: + case ERR_CONSTR1: + return true; + default: return false; + } + } + } + + enum GenericKind { + NONE(""), + ONE("<X>"), + TWO("<X,Y>"); + + String typeParameters; + + GenericKind(String typeParameters) { + this.typeParameters = typeParameters; + } + } + + enum QualifierKind { + THIS("this"), + SUPER("super"), + NEW("new Foo()"), + METHOD("m()"), + FIELD("a.f"), + UBOUND_SIMPLE("A"), + UNBOUND_GENERIC1("A<X>"), + UNBOUND_GENERIC2("A<X, Y>"), + UNBOUND_GENERIC3("A<? extends X, ? super Y>"); + + String qualifier; + + QualifierKind(String qualifier) { + this.qualifier = qualifier; + } + } + + enum ExprKind { + NONE("#R#S"), + SINGLE_PAREN1("(#R#S)"), + SINGLE_PAREN2("(#R)#S"), + DOUBLE_PAREN1("((#R#S))"), + DOUBLE_PAREN2("((#R)#S)"), + DOUBLE_PAREN3("((#R))#S"); + + String expressionTemplate; + + ExprKind(String expressionTemplate) { + this.expressionTemplate = expressionTemplate; + } + + String expressionString(ReferenceKind rk, QualifierKind qk, GenericKind gk, SubExprKind sk) { + return expressionTemplate + .replaceAll("#R", rk.getReferenceString(qk, gk)) + .replaceAll("#S", sk.subExpression); + } + } + + enum SubExprKind { + NONE(""), + SELECT_FIELD(".f"), + SELECT_METHOD(".f()"), + SELECT_NEW(".new Foo()"), + POSTINC("++"), + POSTDEC("--"); + + String subExpression; + + SubExprKind(String subExpression) { + this.subExpression = subExpression; + } + } + + public static void main(String... args) throws Exception { + + //create default shared JavaCompiler - reused across multiple compilations + JavaCompiler comp = ToolProvider.getSystemJavaCompiler(); + StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null); + + for (ReferenceKind rk : ReferenceKind.values()) { + for (QualifierKind qk : QualifierKind.values()) { + for (GenericKind gk : GenericKind.values()) { + for (SubExprKind sk : SubExprKind.values()) { + for (ExprKind ek : ExprKind.values()) { + new MethodReferenceParserTest(rk, qk, gk, sk, ek).run(comp, fm); + } + } + } + } + } + System.out.println("Total check executed: " + checkCount); + } + + ReferenceKind rk; + QualifierKind qk; + GenericKind gk; + SubExprKind sk; + ExprKind ek; + JavaSource source; + DiagnosticChecker diagChecker; + + MethodReferenceParserTest(ReferenceKind rk, QualifierKind qk, GenericKind gk, SubExprKind sk, ExprKind ek) { + this.rk = rk; + this.qk = qk; + this.gk = gk; + this.sk = sk; + this.ek = ek; + this.source = new JavaSource(); + this.diagChecker = new DiagnosticChecker(); + } + + class JavaSource extends SimpleJavaFileObject { + + String template = "class Test {\n" + + " SAM s = #E;\n" + + "}"; + + String source; + + public JavaSource() { + super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); + source = template.replaceAll("#E", ek.expressionString(rk, qk, gk, sk)); + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return source; + } + } + + void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception { + JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker, + Arrays.asList("-XDallowMethodReferences"), null, Arrays.asList(source)); + try { + ct.parse(); + } catch (Throwable ex) { + throw new AssertionError("Error thrown when parsing the following source:\n" + source.getCharContent(true)); + } + check(); + } + + void check() { + checkCount++; + + if (diagChecker.errorFound != rk.erroneous()) { + throw new Error("invalid diagnostics for source:\n" + + source.getCharContent(true) + + "\nFound error: " + diagChecker.errorFound + + "\nExpected error: " + rk.erroneous()); + } + } + + static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> { + + boolean errorFound; + + public void report(Diagnostic<? extends JavaFileObject> diagnostic) { + if (diagnostic.getKind() == Diagnostic.Kind.ERROR) { + errorFound = true; + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/parser/JavacParserTest.java Thu Dec 15 15:57:51 2011 -0800 @@ -0,0 +1,883 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7073631 + * @summary tests error and diagnostics positions + * @author Jan Lahoda + */ + +import com.sun.source.tree.BinaryTree; +import com.sun.source.tree.BlockTree; +import com.sun.source.tree.ClassTree; +import com.sun.source.tree.CompilationUnitTree; +import com.sun.source.tree.ErroneousTree; +import com.sun.source.tree.ExpressionStatementTree; +import com.sun.source.tree.ExpressionTree; +import com.sun.source.tree.MethodInvocationTree; +import com.sun.source.tree.MethodTree; +import com.sun.source.tree.ModifiersTree; +import com.sun.source.tree.StatementTree; +import com.sun.source.tree.Tree; +import com.sun.source.tree.Tree.Kind; +import com.sun.source.tree.VariableTree; +import com.sun.source.tree.WhileLoopTree; +import com.sun.source.util.SourcePositions; +import com.sun.source.util.TreeScanner; +import com.sun.source.util.Trees; +import com.sun.tools.javac.api.JavacTaskImpl; +import com.sun.tools.javac.tree.JCTree; +import java.io.IOException; +import java.net.URI; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import javax.tools.Diagnostic; +import javax.tools.DiagnosticCollector; +import javax.tools.DiagnosticListener; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.SimpleJavaFileObject; +import javax.tools.ToolProvider; + +public class JavacParserTest extends TestCase { + final JavaCompiler tool; + public JavacParserTest(String testName) { + tool = ToolProvider.getSystemJavaCompiler(); + System.out.println("java.home=" + System.getProperty("java.home")); + } + + 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; + } + } + /* + * converts Windows to Unix style LFs for comparing strings + */ + private String normalize(String in) { + return in.replace(System.getProperty("line.separator"), "\n"); + } + + public CompilationUnitTree getCompilationUnitTree(String code) throws IOException { + + JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, null, + null, Arrays.asList(new MyFileObject(code))); + CompilationUnitTree cut = ct.parse().iterator().next(); + return cut; + } + + public List<String> getErroneousTreeValues(ErroneousTree node) { + + List<String> values = new ArrayList<>(); + if (node.getErrorTrees() != null) { + for (Tree t : node.getErrorTrees()) { + values.add(t.toString()); + } + } else { + throw new RuntimeException("ERROR: No Erroneous tree " + + "has been created."); + } + return values; + } + + public void testPositionForSuperConstructorCalls() throws IOException { + assert tool != null; + + String code = "package test; public class Test {public Test() {super();}}"; + + JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, null, + null, Arrays.asList(new MyFileObject(code))); + CompilationUnitTree cut = ct.parse().iterator().next(); + SourcePositions pos = Trees.instance(ct).getSourcePositions(); + + MethodTree method = + (MethodTree) ((ClassTree) cut.getTypeDecls().get(0)).getMembers().get(0); + ExpressionStatementTree es = + (ExpressionStatementTree) method.getBody().getStatements().get(0); + + final int esStartPos = code.indexOf(es.toString()); + final int esEndPos = esStartPos + es.toString().length(); + assertEquals("testPositionForSuperConstructorCalls", + esStartPos, pos.getStartPosition(cut, es)); + assertEquals("testPositionForSuperConstructorCalls", + esEndPos, pos.getEndPosition(cut, es)); + + MethodInvocationTree mit = (MethodInvocationTree) es.getExpression(); + + final int mitStartPos = code.indexOf(mit.toString()); + final int mitEndPos = mitStartPos + mit.toString().length(); + assertEquals("testPositionForSuperConstructorCalls", + mitStartPos, pos.getStartPosition(cut, mit)); + assertEquals("testPositionForSuperConstructorCalls", + mitEndPos, pos.getEndPosition(cut, mit)); + + final int methodStartPos = mitStartPos; + final int methodEndPos = methodStartPos + mit.getMethodSelect().toString().length(); + assertEquals("testPositionForSuperConstructorCalls", + methodStartPos, pos.getStartPosition(cut, mit.getMethodSelect())); + assertEquals("testPositionForSuperConstructorCalls", + methodEndPos, pos.getEndPosition(cut, mit.getMethodSelect())); + + } + + public void testPositionForEnumModifiers() throws IOException { + + String code = "package test; public enum Test {A;}"; + + JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, null, + null, Arrays.asList(new MyFileObject(code))); + CompilationUnitTree cut = ct.parse().iterator().next(); + SourcePositions pos = Trees.instance(ct).getSourcePositions(); + + ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); + ModifiersTree mt = clazz.getModifiers(); + + assertEquals("testPositionForEnumModifiers", + 38 - 24, pos.getStartPosition(cut, mt)); + assertEquals("testPositionForEnumModifiers", + 44 - 24, pos.getEndPosition(cut, mt)); + } + + public void testNewClassWithEnclosing() throws IOException { + + + String code = "package test; class Test { " + + "class d {} private void method() { " + + "Object o = Test.this.new d(); } }"; + + JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, null, + null, Arrays.asList(new MyFileObject(code))); + CompilationUnitTree cut = ct.parse().iterator().next(); + SourcePositions pos = Trees.instance(ct).getSourcePositions(); + + ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); + ExpressionTree est = + ((VariableTree) ((MethodTree) clazz.getMembers().get(1)).getBody().getStatements().get(0)).getInitializer(); + + assertEquals("testNewClassWithEnclosing", + 97 - 24, pos.getStartPosition(cut, est)); + assertEquals("testNewClassWithEnclosing", + 114 - 24, pos.getEndPosition(cut, est)); + } + + public void testPreferredPositionForBinaryOp() throws IOException { + + String code = "package test; public class Test {" + + "private void test() {" + + "Object o = null; boolean b = o != null && o instanceof String;" + + "} private Test() {}}"; + + CompilationUnitTree cut = getCompilationUnitTree(code); + 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; + int condStartPos = code.indexOf("&&"); + assertEquals("testPreferredPositionForBinaryOp", + condStartPos, condJC.pos); + } + + public void testPositionBrokenSource126732a() throws IOException { + String[] commands = new String[]{ + "return Runnable()", + "do { } while (true)", + "throw UnsupportedOperationException()", + "assert true", + "1 + 1",}; + + for (String command : commands) { + + String code = "package test;\n" + + "public class Test {\n" + + " public static void test() {\n" + + " " + command + " {\n" + + " new Runnable() {\n" + + " };\n" + + " }\n" + + "}"; + JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, + null, 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); + List<? extends StatementTree> statements = + method.getBody().getStatements(); + + StatementTree ret = statements.get(0); + StatementTree block = statements.get(1); + + Trees t = Trees.instance(ct); + int len = code.indexOf(command + " {") + (command + " ").length(); + assertEquals(command, len, + t.getSourcePositions().getEndPosition(cut, ret)); + assertEquals(command, len, + t.getSourcePositions().getStartPosition(cut, block)); + } + } + + public void testPositionBrokenSource126732b() throws IOException { + String[] commands = new String[]{ + "break", + "break A", + "continue ", + "continue A",}; + + for (String command : commands) { + + String code = "package test;\n" + + "public class Test {\n" + + " public static void test() {\n" + + " while (true) {\n" + + " " + command + " {\n" + + " new Runnable() {\n" + + " };\n" + + " }\n" + + " }\n" + + "}"; + + JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, + null, 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); + List<? extends StatementTree> statements = + ((BlockTree) ((WhileLoopTree) method.getBody().getStatements().get(0)).getStatement()).getStatements(); + + StatementTree ret = statements.get(0); + StatementTree block = statements.get(1); + + Trees t = Trees.instance(ct); + int len = code.indexOf(command + " {") + (command + " ").length(); + assertEquals(command, len, + t.getSourcePositions().getEndPosition(cut, ret)); + assertEquals(command, len, + t.getSourcePositions().getStartPosition(cut, block)); + } + } + + public void testErrorRecoveryForEnhancedForLoop142381() throws IOException { + + String code = "package test; class Test { " + + "private void method() { " + + "java.util.Set<String> s = null; for (a : s) {} } }"; + + final List<Diagnostic<? extends JavaFileObject>> errors = + new LinkedList<Diagnostic<? extends JavaFileObject>>(); + + JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, + new DiagnosticListener<JavaFileObject>() { + public void report(Diagnostic<? extends JavaFileObject> diagnostic) { + errors.add(diagnostic); + } + }, null, null, Arrays.asList(new MyFileObject(code))); + + CompilationUnitTree cut = ct.parse().iterator().next(); + + ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); + StatementTree forStatement = + ((MethodTree) clazz.getMembers().get(0)).getBody().getStatements().get(1); + + assertEquals("testErrorRecoveryForEnhancedForLoop142381", + Kind.ENHANCED_FOR_LOOP, forStatement.getKind()); + assertFalse("testErrorRecoveryForEnhancedForLoop142381", errors.isEmpty()); + } + + public void testPositionAnnotationNoPackage187551() throws IOException { + + String code = "\n@interface Test {}"; + + JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, null, + null, Arrays.asList(new MyFileObject(code))); + + CompilationUnitTree cut = ct.parse().iterator().next(); + ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); + Trees t = Trees.instance(ct); + + assertEquals("testPositionAnnotationNoPackage187551", + 1, t.getSourcePositions().getStartPosition(cut, clazz)); + } + + public void testPositionsSane() throws IOException { + performPositionsSanityTest("package test; class Test { " + + "private void method() { " + + "java.util.List<? extends java.util.List<? extends String>> l; " + + "} }"); + performPositionsSanityTest("package test; class Test { " + + "private void method() { " + + "java.util.List<? super java.util.List<? super String>> l; " + + "} }"); + performPositionsSanityTest("package test; class Test { " + + "private void method() { " + + "java.util.List<? super java.util.List<?>> l; } }"); + } + + private void performPositionsSanityTest(String code) throws IOException { + + final List<Diagnostic<? extends JavaFileObject>> errors = + new LinkedList<Diagnostic<? extends JavaFileObject>>(); + + JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, + new DiagnosticListener<JavaFileObject>() { + + public void report(Diagnostic<? extends JavaFileObject> diagnostic) { + errors.add(diagnostic); + } + }, null, null, Arrays.asList(new MyFileObject(code))); + + final CompilationUnitTree cut = ct.parse().iterator().next(); + final Trees trees = Trees.instance(ct); + + new TreeScanner<Void, Void>() { + + private long parentStart = 0; + private long parentEnd = Integer.MAX_VALUE; + + @Override + public Void scan(Tree node, Void p) { + if (node == null) { + return null; + } + + long start = trees.getSourcePositions().getStartPosition(cut, node); + + if (start == (-1)) { + return null; //synthetic tree + } + assertTrue(node.toString() + ":" + start + "/" + parentStart, + parentStart <= start); + + long prevParentStart = parentStart; + + parentStart = start; + + long end = trees.getSourcePositions().getEndPosition(cut, node); + + assertTrue(node.toString() + ":" + end + "/" + parentEnd, + end <= parentEnd); + + long prevParentEnd = parentEnd; + + parentEnd = end; + + super.scan(node, p); + + parentStart = prevParentStart; + parentEnd = prevParentEnd; + + return null; + } + + private void assertTrue(String message, boolean b) { + if (!b) fail(message); + } + }.scan(cut, null); + } + + public void testCorrectWilcardPositions() throws IOException { + performWildcardPositionsTest("package test; import java.util.List; " + + "class Test { private void method() { List<? extends List<? extends String>> l; } }", + + Arrays.asList("List<? extends List<? extends String>> l;", + "List<? extends List<? extends String>>", + "List", + "? extends List<? extends String>", + "List<? extends String>", + "List", + "? extends String", + "String")); + performWildcardPositionsTest("package test; import java.util.List; " + + "class Test { private void method() { List<? super List<? super String>> l; } }", + + Arrays.asList("List<? super List<? super String>> l;", + "List<? super List<? super String>>", + "List", + "? super List<? super String>", + "List<? super String>", + "List", + "? super String", + "String")); + performWildcardPositionsTest("package test; import java.util.List; " + + "class Test { private void method() { List<? super List<?>> l; } }", + + Arrays.asList("List<? super List<?>> l;", + "List<? super List<?>>", + "List", + "? super List<?>", + "List<?>", + "List", + "?")); + performWildcardPositionsTest("package test; import java.util.List; " + + "class Test { private void method() { " + + "List<? extends List<? extends List<? extends String>>> l; } }", + + Arrays.asList("List<? extends List<? extends List<? extends String>>> l;", + "List<? extends List<? extends List<? extends String>>>", + "List", + "? extends List<? extends List<? extends String>>", + "List<? extends List<? extends String>>", + "List", + "? extends List<? extends String>", + "List<? extends String>", + "List", + "? extends String", + "String")); + performWildcardPositionsTest("package test; import java.util.List; " + + "class Test { private void method() { " + + "List<? extends List<? extends List<? extends String >>> l; } }", + Arrays.asList("List<? extends List<? extends List<? extends String >>> l;", + "List<? extends List<? extends List<? extends String >>>", + "List", + "? extends List<? extends List<? extends String >>", + "List<? extends List<? extends String >>", + "List", + "? extends List<? extends String >", + "List<? extends String >", + "List", + "? extends String", + "String")); + } + + public void performWildcardPositionsTest(final String code, + List<String> golden) throws IOException { + + final List<Diagnostic<? extends JavaFileObject>> errors = + new LinkedList<Diagnostic<? extends JavaFileObject>>(); + + JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, + new DiagnosticListener<JavaFileObject>() { + public void report(Diagnostic<? extends JavaFileObject> diagnostic) { + errors.add(diagnostic); + } + }, null, null, Arrays.asList(new MyFileObject(code))); + + final CompilationUnitTree cut = ct.parse().iterator().next(); + final List<String> content = new LinkedList<String>(); + final Trees trees = Trees.instance(ct); + + new TreeScanner<Void, Void>() { + @Override + public Void scan(Tree node, Void p) { + if (node == null) { + return null; + } + long start = trees.getSourcePositions().getStartPosition(cut, node); + + if (start == (-1)) { + return null; //synthetic tree + } + long end = trees.getSourcePositions().getEndPosition(cut, node); + String s = code.substring((int) start, (int) end); + content.add(s); + + return super.scan(node, p); + } + }.scan(((MethodTree) ((ClassTree) cut.getTypeDecls().get(0)).getMembers().get(0)).getBody().getStatements().get(0), null); + + assertEquals("performWildcardPositionsTest",golden.toString(), + content.toString()); + } + + public void testStartPositionForMethodWithoutModifiers() throws IOException { + + String code = "package t; class Test { <T> void t() {} }"; + + JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, null, + null, Arrays.asList(new MyFileObject(code))); + CompilationUnitTree cut = ct.parse().iterator().next(); + ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); + MethodTree mt = (MethodTree) clazz.getMembers().get(0); + Trees t = Trees.instance(ct); + int start = (int) t.getSourcePositions().getStartPosition(cut, mt); + int end = (int) t.getSourcePositions().getEndPosition(cut, mt); + + assertEquals("testStartPositionForMethodWithoutModifiers", + "<T> void t() {}", code.substring(start, end)); + } + + public void testStartPositionEnumConstantInit() throws IOException { + + String code = "package t; enum Test { AAA; }"; + + JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, null, + null, Arrays.asList(new MyFileObject(code))); + CompilationUnitTree cut = ct.parse().iterator().next(); + ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); + VariableTree enumAAA = (VariableTree) clazz.getMembers().get(0); + Trees t = Trees.instance(ct); + int start = (int) t.getSourcePositions().getStartPosition(cut, + enumAAA.getInitializer()); + + assertEquals("testStartPositionEnumConstantInit", -1, start); + } + + public void testVariableInIfThen1() throws IOException { + + String code = "package t; class Test { " + + "private static void t(String name) { " + + "if (name != null) String nn = name.trim(); } }"; + + DiagnosticCollector<JavaFileObject> coll = + new DiagnosticCollector<JavaFileObject>(); + + JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, coll, null, + null, Arrays.asList(new MyFileObject(code))); + + ct.parse(); + + List<String> codes = new LinkedList<String>(); + + for (Diagnostic<? extends JavaFileObject> d : coll.getDiagnostics()) { + codes.add(d.getCode()); + } + + assertEquals("testVariableInIfThen1", + Arrays.<String>asList("compiler.err.variable.not.allowed"), + codes); + } + + public void testVariableInIfThen2() throws IOException { + + String code = "package t; class Test { " + + "private static void t(String name) { " + + "if (name != null) class X {} } }"; + DiagnosticCollector<JavaFileObject> coll = + new DiagnosticCollector<JavaFileObject>(); + JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, coll, null, + null, Arrays.asList(new MyFileObject(code))); + + ct.parse(); + + List<String> codes = new LinkedList<String>(); + + for (Diagnostic<? extends JavaFileObject> d : coll.getDiagnostics()) { + codes.add(d.getCode()); + } + + assertEquals("testVariableInIfThen2", + Arrays.<String>asList("compiler.err.class.not.allowed"), codes); + } + + public void testVariableInIfThen3() throws IOException { + + String code = "package t; class Test { "+ + "private static void t(String name) { " + + "if (name != null) abstract } }"; + DiagnosticCollector<JavaFileObject> coll = + new DiagnosticCollector<JavaFileObject>(); + JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, coll, null, + null, Arrays.asList(new MyFileObject(code))); + + ct.parse(); + + List<String> codes = new LinkedList<String>(); + + for (Diagnostic<? extends JavaFileObject> d : coll.getDiagnostics()) { + codes.add(d.getCode()); + } + + assertEquals("testVariableInIfThen3", + Arrays.<String>asList("compiler.err.illegal.start.of.expr"), + codes); + } + + //see javac bug #6882235, NB bug #98234: + public void testMissingExponent() throws IOException { + + String code = "\nclass Test { { System.err.println(0e); } }"; + + JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, null, + null, Arrays.asList(new MyFileObject(code))); + + assertNotNull(ct.parse().iterator().next()); + } + + public void testTryResourcePos() throws IOException { + + final String code = "package t; class Test { " + + "{ try (java.io.InputStream in = null) { } } }"; + + CompilationUnitTree cut = getCompilationUnitTree(code); + + new TreeScanner<Void, Void>() { + @Override + public Void visitVariable(VariableTree node, Void p) { + if ("in".contentEquals(node.getName())) { + JCTree.JCVariableDecl var = (JCTree.JCVariableDecl) node; + System.out.println(node.getName() + "," + var.pos); + assertEquals("testTryResourcePos", "in = null) { } } }", + code.substring(var.pos)); + } + return super.visitVariable(node, p); + } + }.scan(cut, null); + } + + public void testVarPos() throws IOException { + + final String code = "package t; class Test { " + + "{ java.io.InputStream in = null; } }"; + + CompilationUnitTree cut = getCompilationUnitTree(code); + + new TreeScanner<Void, Void>() { + + @Override + public Void visitVariable(VariableTree node, Void p) { + if ("in".contentEquals(node.getName())) { + JCTree.JCVariableDecl var = (JCTree.JCVariableDecl) node; + assertEquals("testVarPos","in = null; } }", + code.substring(var.pos)); + } + return super.visitVariable(node, p); + } + }.scan(cut, null); + } + + // expected erroneous tree: int x = y;(ERROR); + public void testOperatorMissingError() throws IOException { + + String code = "package test; public class ErrorTest { " + + "void method() { int x = y z } }"; + CompilationUnitTree cut = getCompilationUnitTree(code); + final List<String> values = new ArrayList<>(); + final List<String> expectedValues = + new ArrayList<>(Arrays.asList("[z]")); + + new TreeScanner<Void, Void>() { + + @Override + public Void visitErroneous(ErroneousTree node, Void p) { + + values.add(getErroneousTreeValues(node).toString()); + return null; + + } + }.scan(cut, null); + + assertEquals("testSwitchError: The Erroneous tree " + + "error values: " + values + + " do not match expected error values: " + + expectedValues, values, expectedValues); + } + + //expected erroneous tree: String s = (ERROR); + public void testMissingParenthesisError() throws IOException { + + String code = "package test; public class ErrorTest { " + + "void f() {String s = new String; } }"; + CompilationUnitTree cut = getCompilationUnitTree(code); + final List<String> values = new ArrayList<>(); + final List<String> expectedValues = + new ArrayList<>(Arrays.asList("[new String()]")); + + new TreeScanner<Void, Void>() { + + @Override + public Void visitErroneous(ErroneousTree node, Void p) { + + values.add(getErroneousTreeValues(node).toString()); + return null; + } + }.scan(cut, null); + + assertEquals("testSwitchError: The Erroneous tree " + + "error values: " + values + + " do not match expected error values: " + + expectedValues, values, expectedValues); + } + + //expected erroneous tree: package test; (ERROR)(ERROR) + public void testMissingClassError() throws IOException { + + String code = "package Test; clas ErrorTest { " + + "void f() {String s = new String(); } }"; + CompilationUnitTree cut = getCompilationUnitTree(code); + final List<String> values = new ArrayList<>(); + final List<String> expectedValues = + new ArrayList<>(Arrays.asList("[, clas]", "[]")); + + new TreeScanner<Void, Void>() { + + @Override + public Void visitErroneous(ErroneousTree node, Void p) { + + values.add(getErroneousTreeValues(node).toString()); + return null; + } + }.scan(cut, null); + + assertEquals("testSwitchError: The Erroneous tree " + + "error values: " + values + + " do not match expected error values: " + + expectedValues, values, expectedValues); + } + + //expected erroneous tree: void m1(int i) {(ERROR);{(ERROR);} + public void testSwitchError() throws IOException { + + String code = "package test; public class ErrorTest { " + + "int numDays; void m1(int i) { switchh {i} { case 1: " + + "numDays = 31; break; } } }"; + CompilationUnitTree cut = getCompilationUnitTree(code); + final List<String> values = new ArrayList<>(); + final List<String> expectedValues = + new ArrayList<>(Arrays.asList("[switchh]", "[i]")); + + new TreeScanner<Void, Void>() { + + @Override + public Void visitErroneous(ErroneousTree node, Void p) { + + values.add(getErroneousTreeValues(node).toString()); + return null; + } + }.scan(cut, null); + + assertEquals("testSwitchError: The Erroneous tree " + + "error values: " + values + + " do not match expected error values: " + + expectedValues, values, expectedValues); + } + + //expected erroneous tree: class ErrorTest {(ERROR) + public void testMethodError() throws IOException { + + String code = "package Test; class ErrorTest { " + + "static final void f) {String s = new String(); } }"; + CompilationUnitTree cut = getCompilationUnitTree(code); + final List<String> values = new ArrayList<>(); + final List<String> expectedValues = + new ArrayList<>(Arrays.asList("[\nstatic final void f();]")); + + new TreeScanner<Void, Void>() { + + @Override + public Void visitErroneous(ErroneousTree node, Void p) { + + values.add(normalize(getErroneousTreeValues(node).toString())); + return null; + } + }.scan(cut, null); + + assertEquals("testMethodError: The Erroneous tree " + + "error value: " + values + + " does not match expected error values: " + + expectedValues, values, expectedValues); + } + + void testsNotWorking() throws IOException { + + // Fails with nb-javac, needs further investigation + testPositionBrokenSource126732a(); + testPositionBrokenSource126732b(); + + // Fails, these tests yet to be addressed + testVariableInIfThen1(); + testVariableInIfThen2(); + testPositionForEnumModifiers(); + testStartPositionEnumConstantInit(); + } + void testPositions() throws IOException { + testPositionsSane(); + testCorrectWilcardPositions(); + testPositionAnnotationNoPackage187551(); + testPositionForSuperConstructorCalls(); + testPreferredPositionForBinaryOp(); + testStartPositionForMethodWithoutModifiers(); + testVarPos(); + testVariableInIfThen3(); + testMissingExponent(); + testTryResourcePos(); + testOperatorMissingError(); + testMissingParenthesisError(); + testMissingClassError(); + testSwitchError(); + testMethodError(); + } + + public static void main(String... args) throws IOException { + JavacParserTest jpt = new JavacParserTest("JavacParserTest"); + jpt.testPositions(); + System.out.println("PASS"); + } +} + +abstract class TestCase { + + void assertEquals(String message, int i, int pos) { + if (i != pos) { + fail(message); + } + } + + void assertFalse(String message, boolean empty) { + throw new UnsupportedOperationException("Not yet implemented"); + } + + void assertEquals(String message, int i, long l) { + if (i != l) { + fail(message + ":" + i + ":" + l); + } + } + + void assertEquals(String message, Object o1, Object o2) { + System.out.println(o1); + System.out.println(o2); + if (o1 != null && o2 != null && !o1.equals(o2)) { + fail(message); + } + if (o1 == null && o2 != null) { + fail(message); + } + } + + void assertNotNull(Object o) { + if (o == null) { + fail(); + } + } + + void fail() { + fail("test failed"); + } + + void fail(String message) { + throw new RuntimeException(message); + } +}
--- a/test/tools/javac/parser/netbeans/JavacParserTest.java Thu Dec 15 15:47:47 2011 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,716 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 7073631 - * @summary tests error and diagnostics positions - * @author jan.lahoda@oracle.com - */ - -import com.sun.source.tree.BinaryTree; -import com.sun.source.tree.BlockTree; -import com.sun.source.tree.ClassTree; -import com.sun.source.tree.CompilationUnitTree; -import com.sun.source.tree.ExpressionStatementTree; -import com.sun.source.tree.ExpressionTree; -import com.sun.source.tree.MethodInvocationTree; -import com.sun.source.tree.MethodTree; -import com.sun.source.tree.ModifiersTree; -import com.sun.source.tree.StatementTree; -import com.sun.source.tree.Tree; -import com.sun.source.tree.Tree.Kind; -import com.sun.source.tree.VariableTree; -import com.sun.source.tree.WhileLoopTree; -import com.sun.source.util.SourcePositions; -import com.sun.source.util.TreeScanner; -import com.sun.source.util.Trees; -import com.sun.tools.javac.api.JavacTaskImpl; -import com.sun.tools.javac.tree.JCTree; -import java.io.IOException; -import java.net.URI; -import java.util.Arrays; -import java.util.LinkedList; -import java.util.List; -import javax.tools.Diagnostic; -import javax.tools.DiagnosticCollector; -import javax.tools.DiagnosticListener; -import javax.tools.JavaCompiler; -import javax.tools.JavaFileObject; -import javax.tools.SimpleJavaFileObject; -import javax.tools.ToolProvider; - -public class JavacParserTest extends TestCase { - final JavaCompiler tool; - public JavacParserTest(String testName) { - tool = ToolProvider.getSystemJavaCompiler(); - System.out.println("java.home=" + System.getProperty("java.home")); - } - - 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; - } - } - - public void testPositionForSuperConstructorCalls() throws IOException { - assert tool != null; - - String code = "package test; public class Test {public Test() {super();}}"; - - JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, null, - null, Arrays.asList(new MyFileObject(code))); - CompilationUnitTree cut = ct.parse().iterator().next(); - SourcePositions pos = Trees.instance(ct).getSourcePositions(); - - MethodTree method = - (MethodTree) ((ClassTree) cut.getTypeDecls().get(0)).getMembers().get(0); - ExpressionStatementTree es = - (ExpressionStatementTree) method.getBody().getStatements().get(0); - - assertEquals("testPositionForSuperConstructorCalls", - 72 - 24, pos.getStartPosition(cut, es)); - assertEquals("testPositionForSuperConstructorCalls", - 80 - 24, pos.getEndPosition(cut, es)); - - MethodInvocationTree mit = (MethodInvocationTree) es.getExpression(); - - assertEquals("testPositionForSuperConstructorCalls", - 72 - 24, pos.getStartPosition(cut, mit)); - assertEquals("testPositionForSuperConstructorCalls", - 79 - 24, pos.getEndPosition(cut, mit)); - - assertEquals("testPositionForSuperConstructorCalls", - 72 - 24, pos.getStartPosition(cut, mit.getMethodSelect())); - assertEquals("testPositionForSuperConstructorCalls", - 77 - 24, pos.getEndPosition(cut, mit.getMethodSelect())); - - } - - public void testPositionForEnumModifiers() throws IOException { - - String code = "package test; public enum Test {A;}"; - - JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, null, - null, Arrays.asList(new MyFileObject(code))); - CompilationUnitTree cut = ct.parse().iterator().next(); - SourcePositions pos = Trees.instance(ct).getSourcePositions(); - - ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); - ModifiersTree mt = clazz.getModifiers(); - - assertEquals("testPositionForEnumModifiers", - 38 - 24, pos.getStartPosition(cut, mt)); - assertEquals("testPositionForEnumModifiers", - 44 - 24, pos.getEndPosition(cut, mt)); - } - - public void testNewClassWithEnclosing() throws IOException { - - - String code = "package test; class Test { " + - "class d {} private void method() { " + - "Object o = Test.this.new d(); } }"; - - JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, null, - null, Arrays.asList(new MyFileObject(code))); - CompilationUnitTree cut = ct.parse().iterator().next(); - SourcePositions pos = Trees.instance(ct).getSourcePositions(); - - ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); - ExpressionTree est = - ((VariableTree) ((MethodTree) clazz.getMembers().get(1)).getBody().getStatements().get(0)).getInitializer(); - - assertEquals("testNewClassWithEnclosing", - 97 - 24, pos.getStartPosition(cut, est)); - assertEquals("testNewClassWithEnclosing", - 114 - 24, pos.getEndPosition(cut, est)); - } - - public void testPreferredPositionForBinaryOp() throws IOException { - - 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, null, - 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; - - assertEquals("testNewClassWithEnclosing", - 117 - 24, condJC.pos); - } - - public void testPositionBrokenSource126732a() throws IOException { - String[] commands = new String[]{ - "return Runnable()", - "do { } while (true)", - "throw UnsupportedOperationException()", - "assert true", - "1 + 1",}; - - for (String command : commands) { - - String code = "package test;\n" - + "public class Test {\n" - + " public static void test() {\n" - + " " + command + " {\n" - + " new Runnable() {\n" - + " };\n" - + " }\n" - + "}"; - JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, - null, 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); - List<? extends StatementTree> statements = - method.getBody().getStatements(); - - StatementTree ret = statements.get(0); - StatementTree block = statements.get(1); - - Trees t = Trees.instance(ct); - int len = code.indexOf(command + " {") + (command + " ").length(); - assertEquals(command, len, - t.getSourcePositions().getEndPosition(cut, ret)); - assertEquals(command, len, - t.getSourcePositions().getStartPosition(cut, block)); - } - } - - public void testPositionBrokenSource126732b() throws IOException { - String[] commands = new String[]{ - "break", - "break A", - "continue ", - "continue A",}; - - for (String command : commands) { - - String code = "package test;\n" - + "public class Test {\n" - + " public static void test() {\n" - + " while (true) {\n" - + " " + command + " {\n" - + " new Runnable() {\n" - + " };\n" - + " }\n" - + " }\n" - + "}"; - - JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, - null, 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); - List<? extends StatementTree> statements = - ((BlockTree) ((WhileLoopTree) method.getBody().getStatements().get(0)).getStatement()).getStatements(); - - StatementTree ret = statements.get(0); - StatementTree block = statements.get(1); - - Trees t = Trees.instance(ct); - int len = code.indexOf(command + " {") + (command + " ").length(); - assertEquals(command, len, - t.getSourcePositions().getEndPosition(cut, ret)); - assertEquals(command, len, - t.getSourcePositions().getStartPosition(cut, block)); - } - } - - public void testErrorRecoveryForEnhancedForLoop142381() throws IOException { - - String code = "package test; class Test { " + - "private void method() { " + - "java.util.Set<String> s = null; for (a : s) {} } }"; - - final List<Diagnostic<? extends JavaFileObject>> errors = - new LinkedList<Diagnostic<? extends JavaFileObject>>(); - - JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, - new DiagnosticListener<JavaFileObject>() { - public void report(Diagnostic<? extends JavaFileObject> diagnostic) { - errors.add(diagnostic); - } - }, null, null, Arrays.asList(new MyFileObject(code))); - - CompilationUnitTree cut = ct.parse().iterator().next(); - - ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); - StatementTree forStatement = - ((MethodTree) clazz.getMembers().get(0)).getBody().getStatements().get(1); - - assertEquals("testErrorRecoveryForEnhancedForLoop142381", - Kind.ENHANCED_FOR_LOOP, forStatement.getKind()); - assertFalse("testErrorRecoveryForEnhancedForLoop142381", errors.isEmpty()); - } - - public void testPositionAnnotationNoPackage187551() throws IOException { - - String code = "\n@interface Test {}"; - - JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, null, - null, Arrays.asList(new MyFileObject(code))); - - CompilationUnitTree cut = ct.parse().iterator().next(); - ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); - Trees t = Trees.instance(ct); - - assertEquals("testPositionAnnotationNoPackage187551", - 1, t.getSourcePositions().getStartPosition(cut, clazz)); - } - - public void testPositionsSane() throws IOException { - performPositionsSanityTest("package test; class Test { " + - "private void method() { " + - "java.util.List<? extends java.util.List<? extends String>> l; " + - "} }"); - performPositionsSanityTest("package test; class Test { " + - "private void method() { " + - "java.util.List<? super java.util.List<? super String>> l; " + - "} }"); - performPositionsSanityTest("package test; class Test { " + - "private void method() { " + - "java.util.List<? super java.util.List<?>> l; } }"); - } - - private void performPositionsSanityTest(String code) throws IOException { - - final List<Diagnostic<? extends JavaFileObject>> errors = - new LinkedList<Diagnostic<? extends JavaFileObject>>(); - - JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, - new DiagnosticListener<JavaFileObject>() { - - public void report(Diagnostic<? extends JavaFileObject> diagnostic) { - errors.add(diagnostic); - } - }, null, null, Arrays.asList(new MyFileObject(code))); - - final CompilationUnitTree cut = ct.parse().iterator().next(); - final Trees trees = Trees.instance(ct); - - new TreeScanner<Void, Void>() { - - private long parentStart = 0; - private long parentEnd = Integer.MAX_VALUE; - - @Override - public Void scan(Tree node, Void p) { - if (node == null) { - return null; - } - - long start = trees.getSourcePositions().getStartPosition(cut, node); - - if (start == (-1)) { - return null; //synthetic tree - } - assertTrue(node.toString() + ":" + start + "/" + parentStart, - parentStart <= start); - - long prevParentStart = parentStart; - - parentStart = start; - - long end = trees.getSourcePositions().getEndPosition(cut, node); - - assertTrue(node.toString() + ":" + end + "/" + parentEnd, - end <= parentEnd); - - long prevParentEnd = parentEnd; - - parentEnd = end; - - super.scan(node, p); - - parentStart = prevParentStart; - parentEnd = prevParentEnd; - - return null; - } - - private void assertTrue(String message, boolean b) { - if (!b) fail(message); - } - }.scan(cut, null); - } - - public void testCorrectWilcardPositions() throws IOException { - performWildcardPositionsTest("package test; import java.util.List; " + - "class Test { private void method() { List<? extends List<? extends String>> l; } }", - - Arrays.asList("List<? extends List<? extends String>> l;", - "List<? extends List<? extends String>>", - "List", - "? extends List<? extends String>", - "List<? extends String>", - "List", - "? extends String", - "String")); - performWildcardPositionsTest("package test; import java.util.List; " + - "class Test { private void method() { List<? super List<? super String>> l; } }", - - Arrays.asList("List<? super List<? super String>> l;", - "List<? super List<? super String>>", - "List", - "? super List<? super String>", - "List<? super String>", - "List", - "? super String", - "String")); - performWildcardPositionsTest("package test; import java.util.List; " + - "class Test { private void method() { List<? super List<?>> l; } }", - - Arrays.asList("List<? super List<?>> l;", - "List<? super List<?>>", - "List", - "? super List<?>", - "List<?>", - "List", - "?")); - performWildcardPositionsTest("package test; import java.util.List; " + - "class Test { private void method() { " + - "List<? extends List<? extends List<? extends String>>> l; } }", - - Arrays.asList("List<? extends List<? extends List<? extends String>>> l;", - "List<? extends List<? extends List<? extends String>>>", - "List", - "? extends List<? extends List<? extends String>>", - "List<? extends List<? extends String>>", - "List", - "? extends List<? extends String>", - "List<? extends String>", - "List", - "? extends String", - "String")); - performWildcardPositionsTest("package test; import java.util.List; " + - "class Test { private void method() { " + - "List<? extends List<? extends List<? extends String >>> l; } }", - Arrays.asList("List<? extends List<? extends List<? extends String >>> l;", - "List<? extends List<? extends List<? extends String >>>", - "List", - "? extends List<? extends List<? extends String >>", - "List<? extends List<? extends String >>", - "List", - "? extends List<? extends String >", - "List<? extends String >", - "List", - "? extends String", - "String")); - } - - public void performWildcardPositionsTest(final String code, - List<String> golden) throws IOException { - - final List<Diagnostic<? extends JavaFileObject>> errors = - new LinkedList<Diagnostic<? extends JavaFileObject>>(); - - JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, - new DiagnosticListener<JavaFileObject>() { - public void report(Diagnostic<? extends JavaFileObject> diagnostic) { - errors.add(diagnostic); - } - }, null, null, Arrays.asList(new MyFileObject(code))); - - final CompilationUnitTree cut = ct.parse().iterator().next(); - final List<String> content = new LinkedList<String>(); - final Trees trees = Trees.instance(ct); - - new TreeScanner<Void, Void>() { - @Override - public Void scan(Tree node, Void p) { - if (node == null) { - return null; - } - long start = trees.getSourcePositions().getStartPosition(cut, node); - - if (start == (-1)) { - return null; //synthetic tree - } - long end = trees.getSourcePositions().getEndPosition(cut, node); - String s = code.substring((int) start, (int) end); - content.add(s); - - return super.scan(node, p); - } - }.scan(((MethodTree) ((ClassTree) cut.getTypeDecls().get(0)).getMembers().get(0)).getBody().getStatements().get(0), null); - - assertEquals("performWildcardPositionsTest",golden.toString(), - content.toString()); - } - - public void testStartPositionForMethodWithoutModifiers() throws IOException { - - String code = "package t; class Test { <T> void t() {} }"; - - JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, null, - null, Arrays.asList(new MyFileObject(code))); - CompilationUnitTree cut = ct.parse().iterator().next(); - ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); - MethodTree mt = (MethodTree) clazz.getMembers().get(0); - Trees t = Trees.instance(ct); - int start = (int) t.getSourcePositions().getStartPosition(cut, mt); - int end = (int) t.getSourcePositions().getEndPosition(cut, mt); - - assertEquals("testStartPositionForMethodWithoutModifiers", - "<T> void t() {}", code.substring(start, end)); - } - - public void testStartPositionEnumConstantInit() throws IOException { - - String code = "package t; enum Test { AAA; }"; - - JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, null, - null, Arrays.asList(new MyFileObject(code))); - CompilationUnitTree cut = ct.parse().iterator().next(); - ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); - VariableTree enumAAA = (VariableTree) clazz.getMembers().get(0); - Trees t = Trees.instance(ct); - int start = (int) t.getSourcePositions().getStartPosition(cut, - enumAAA.getInitializer()); - - assertEquals("testStartPositionEnumConstantInit", -1, start); - } - - public void testVariableInIfThen1() throws IOException { - - String code = "package t; class Test { " + - "private static void t(String name) { " + - "if (name != null) String nn = name.trim(); } }"; - - DiagnosticCollector<JavaFileObject> coll = - new DiagnosticCollector<JavaFileObject>(); - - JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, coll, null, - null, Arrays.asList(new MyFileObject(code))); - - ct.parse(); - - List<String> codes = new LinkedList<String>(); - - for (Diagnostic<? extends JavaFileObject> d : coll.getDiagnostics()) { - codes.add(d.getCode()); - } - - assertEquals("testVariableInIfThen1", - Arrays.<String>asList("compiler.err.variable.not.allowed"), - codes); - } - - public void testVariableInIfThen2() throws IOException { - - String code = "package t; class Test { " + - "private static void t(String name) { " + - "if (name != null) class X {} } }"; - DiagnosticCollector<JavaFileObject> coll = - new DiagnosticCollector<JavaFileObject>(); - JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, coll, null, - null, Arrays.asList(new MyFileObject(code))); - - ct.parse(); - - List<String> codes = new LinkedList<String>(); - - for (Diagnostic<? extends JavaFileObject> d : coll.getDiagnostics()) { - codes.add(d.getCode()); - } - - assertEquals("testVariableInIfThen2", - Arrays.<String>asList("compiler.err.class.not.allowed"), codes); - } - - public void testVariableInIfThen3() throws IOException { - - String code = "package t; class Test { "+ - "private static void t(String name) { " + - "if (name != null) abstract } }"; - DiagnosticCollector<JavaFileObject> coll = - new DiagnosticCollector<JavaFileObject>(); - JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, coll, null, - null, Arrays.asList(new MyFileObject(code))); - - ct.parse(); - - List<String> codes = new LinkedList<String>(); - - for (Diagnostic<? extends JavaFileObject> d : coll.getDiagnostics()) { - codes.add(d.getCode()); - } - - assertEquals("testVariableInIfThen3", - Arrays.<String>asList("compiler.err.illegal.start.of.expr"), - codes); - } - - //see javac bug #6882235, NB bug #98234: - public void testMissingExponent() throws IOException { - - String code = "\nclass Test { { System.err.println(0e); } }"; - - JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, null, - null, Arrays.asList(new MyFileObject(code))); - - assertNotNull(ct.parse().iterator().next()); - } - - public void testTryResourcePos() throws IOException { - - final String code = "package t; class Test { " + - "{ try (java.io.InputStream in = null) { } } }"; - - JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, null, - null, Arrays.asList(new MyFileObject(code))); - CompilationUnitTree cut = ct.parse().iterator().next(); - - new TreeScanner<Void, Void>() { - @Override - public Void visitVariable(VariableTree node, Void p) { - if ("in".contentEquals(node.getName())) { - JCTree.JCVariableDecl var = (JCTree.JCVariableDecl) node; - System.out.println(node.getName() + "," + var.pos); - assertEquals("testTryResourcePos", "in = null) { } } }", - code.substring(var.pos)); - } - return super.visitVariable(node, p); - } - }.scan(cut, null); - } - - public void testVarPos() throws IOException { - - final String code = "package t; class Test { " + - "{ java.io.InputStream in = null; } }"; - - JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, null, - null, Arrays.asList(new MyFileObject(code))); - CompilationUnitTree cut = ct.parse().iterator().next(); - - new TreeScanner<Void, Void>() { - - @Override - public Void visitVariable(VariableTree node, Void p) { - if ("in".contentEquals(node.getName())) { - JCTree.JCVariableDecl var = (JCTree.JCVariableDecl) node; - assertEquals("testVarPos","in = null; } }", - code.substring(var.pos)); - } - return super.visitVariable(node, p); - } - }.scan(cut, null); - } - - void testsNotWorking() throws IOException { - - // Fails with nb-javac, needs further investigation - testPositionBrokenSource126732a(); - testPositionBrokenSource126732b(); - - // Fails, these tests yet to be addressed - testVariableInIfThen1(); - testVariableInIfThen2(); - testPositionForEnumModifiers(); - testStartPositionEnumConstantInit(); - } - void testPositions() throws IOException { - testPositionsSane(); - testCorrectWilcardPositions(); - testPositionAnnotationNoPackage187551(); - testPositionForSuperConstructorCalls(); - testPreferredPositionForBinaryOp(); - testStartPositionForMethodWithoutModifiers(); - testVarPos(); - testVariableInIfThen3(); - testTryResourcePos(); - } - - public static void main(String... args) throws IOException { - JavacParserTest jpt = new JavacParserTest("JavacParserTest"); - jpt.testPositions(); - System.out.println("PASS"); - } -} - -abstract class TestCase { - - void assertEquals(String message, int i, int pos) { - if (i != pos) { - fail(message); - } - } - - void assertFalse(String message, boolean empty) { - throw new UnsupportedOperationException("Not yet implemented"); - } - - void assertEquals(String message, int i, long l) { - if (i != l) { - fail(message + ":" + i + ":" + l); - } - } - - void assertEquals(String message, Object o1, Object o2) { - System.out.println(o1); - System.out.println(o2); - if (o1 != null && o2 != null && !o1.equals(o2)) { - fail(message); - } - if (o1 == null && o2 != null) { - fail(message); - } - } - - void assertNotNull(Object o) { - if (o == null) { - fail(); - } - } - - void fail() { - fail("test failed"); - } - - void fail(String message) { - throw new RuntimeException(message); - } -}
--- a/test/tools/javac/quid/T6999438.out Thu Dec 15 15:47:47 2011 -0800 +++ b/test/tools/javac/quid/T6999438.out Thu Dec 15 15:57:51 2011 -0800 @@ -1,4 +1,4 @@ -T6999438.java:8:9: compiler.err.illegal.char: 35 +T6999438.java:8:8: compiler.err.expected: token.identifier T6999438.java:8:10: compiler.err.illegal.start.of.type T6999438.java:8:25: compiler.err.expected: token.identifier T6999438.java:8:26: compiler.err.expected: ';'