# HG changeset patch # User asaha # Date 1418425022 28800 # Node ID 244e6dc772877dfae6286530f58e11a210a48a3c # Parent d4c7822e9d64efd886f32f5dc8ed4bc899f5f3af# Parent 9b191517a63fce9feda08e856a720690492a7b04 Merge diff -r d4c7822e9d64 -r 244e6dc77287 .hgtags --- a/.hgtags Mon Dec 01 11:39:34 2014 -0800 +++ b/.hgtags Fri Dec 12 14:57:02 2014 -0800 @@ -362,4 +362,6 @@ f18c5b47f27b387d94487890684abe5a554b0d9b jdk8u40-b14 682a6c1aefd766eaf774ffeb1207a5189edf94d6 jdk8u40-b15 74c51ff270c51d17732250411fe9cd5392bc925e jdk8u40-b16 +a12a9932f649dd3df174d3e340527433d3695c49 jdk8u40-b17 +94f30e5fde53e3ddcd3c4e9842349318eae8fe10 jdk8u40-b18 dbae37f50c43453f7d6f22d96adc8b5b6cd1e90d jdk8u45-b00 diff -r d4c7822e9d64 -r 244e6dc77287 src/share/classes/com/sun/tools/javac/comp/Attr.java --- a/src/share/classes/com/sun/tools/javac/comp/Attr.java Mon Dec 01 11:39:34 2014 -0800 +++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java Fri Dec 12 14:57:02 2014 -0800 @@ -3226,8 +3226,9 @@ elt = ((ArrayType)elt.unannotatedType()).elemtype; if (elt.hasTag(TYPEVAR)) { log.error(tree.pos(), "type.var.cant.be.deref"); - result = types.createErrorType(tree.type); - return; + result = tree.type = types.createErrorType(tree.name, site.tsym, site); + tree.sym = tree.type.tsym; + return ; } } @@ -3243,6 +3244,10 @@ // Determine the symbol represented by the selection. env.info.pendingResolutionPhase = null; Symbol sym = selectSym(tree, sitesym, site, env, resultInfo); + if (sym.kind == VAR && sym.name != names._super && env.info.defaultSuperCallSite != null) { + log.error(tree.selected.pos(), "not.encl.class", site.tsym); + sym = syms.errSymbol; + } if (sym.exists() && !isType(sym) && (pkind() & (PCK | TYP)) != 0) { site = capture(site); sym = selectSym(tree, sitesym, site, env, resultInfo); @@ -4499,14 +4504,15 @@ super.visitTypeTest(tree); } public void visitNewClass(JCNewClass tree) { - if (tree.clazz.hasTag(ANNOTATED_TYPE)) { - checkForDeclarationAnnotations(((JCAnnotatedType) tree.clazz).annotations, - tree.clazz.type.tsym); - } - if (tree.def != null) { - checkForDeclarationAnnotations(tree.def.mods.annotations, tree.clazz.type.tsym); - } - if (tree.clazz.type != null) { + if (tree.clazz != null && tree.clazz.type != null) { + if (tree.clazz.hasTag(ANNOTATED_TYPE)) { + checkForDeclarationAnnotations(((JCAnnotatedType) tree.clazz).annotations, + tree.clazz.type.tsym); + } + if (tree.def != null) { + checkForDeclarationAnnotations(tree.def.mods.annotations, tree.clazz.type.tsym); + } + validateAnnotatedType(tree.clazz, tree.clazz.type); } super.visitNewClass(tree); diff -r d4c7822e9d64 -r 244e6dc77287 src/share/classes/com/sun/tools/javac/comp/Flow.java --- a/src/share/classes/com/sun/tools/javac/comp/Flow.java Mon Dec 01 11:39:34 2014 -0800 +++ b/src/share/classes/com/sun/tools/javac/comp/Flow.java Fri Dec 12 14:57:02 2014 -0800 @@ -242,9 +242,15 @@ Log.DiagnosticHandler diagHandler = new Log.DiscardDiagnosticHandler(log); try { new AssignAnalyzer() { + Scope enclosedSymbols = new Scope(env.enclClass.sym); + @Override + public void visitVarDef(JCVariableDecl tree) { + enclosedSymbols.enter(tree.sym); + super.visitVarDef(tree); + } @Override protected boolean trackable(VarSymbol sym) { - return !env.info.scope.includes(sym) && + return enclosedSymbols.includes(sym) && sym.owner.kind == MTH; } }.analyzeTree(env, that); diff -r d4c7822e9d64 -r 244e6dc77287 src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java --- a/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Mon Dec 01 11:39:34 2014 -0800 +++ b/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Fri Dec 12 14:57:02 2014 -0800 @@ -41,6 +41,7 @@ import com.sun.tools.javac.code.Symtab; import com.sun.tools.javac.code.Type; import com.sun.tools.javac.code.Type.MethodType; +import com.sun.tools.javac.code.Type.TypeVar; import com.sun.tools.javac.code.Types; import com.sun.tools.javac.comp.LambdaToMethod.LambdaAnalyzerPreprocessor.*; import com.sun.tools.javac.comp.Lower.BasicFreeVarCollector; @@ -61,6 +62,7 @@ import static com.sun.tools.javac.code.Kinds.*; import static com.sun.tools.javac.code.TypeTag.*; import static com.sun.tools.javac.tree.JCTree.Tag.*; +import javax.lang.model.type.TypeKind; /** * This pass desugars lambda expressions into static methods @@ -321,7 +323,9 @@ ListBuffer syntheticInits = new ListBuffer<>(); - if (!sym.isStatic()) { + if (localContext.methodReferenceReceiver != null) { + syntheticInits.append(localContext.methodReferenceReceiver); + } else if (!sym.isStatic()) { syntheticInits.append(makeThis( sym.owner.enclClass().asType(), localContext.owner.enclClass())); @@ -364,17 +368,10 @@ //first determine the method symbol to be used to generate the sam instance //this is either the method reference symbol, or the bridged reference symbol - Symbol refSym = localContext.needsBridge() - ? localContext.bridgeSym - : localContext.isSignaturePolymorphic() + Symbol refSym = localContext.isSignaturePolymorphic() ? localContext.sigPolySym : tree.sym; - //build the bridge method, if needed - if (localContext.needsBridge()) { - bridgeMemberReference(tree, localContext); - } - //the qualifying expression is treated as a special captured arg JCExpression init; switch(tree.kind) { @@ -744,130 +741,146 @@ // /** - * Generate an adapter method "bridge" for a method reference which cannot - * be used directly. + * Converts a method reference which cannot be used directly into a lambda */ - private class MemberReferenceBridger { + private class MemberReferenceToLambda { private final JCMemberReference tree; private final ReferenceTranslationContext localContext; + private final Symbol owner; private final ListBuffer args = new ListBuffer<>(); private final ListBuffer params = new ListBuffer<>(); - MemberReferenceBridger(JCMemberReference tree, ReferenceTranslationContext localContext) { + private JCExpression receiverExpression = null; + + MemberReferenceToLambda(JCMemberReference tree, ReferenceTranslationContext localContext, Symbol owner) { this.tree = tree; this.localContext = localContext; + this.owner = owner; } - /** - * Generate the bridge - */ - JCMethodDecl bridge() { + JCLambda lambda() { int prevPos = make.pos; try { make.at(tree); - Type samDesc = localContext.bridgedRefSig(); - List samPTypes = samDesc.getParameterTypes(); - //an extra argument is prepended to the signature of the bridge in case - //the member reference is an instance method reference (in which case - //the receiver expression is passed to the bridge itself). - Type recType = null; - switch (tree.kind) { - case IMPLICIT_INNER: - recType = tree.sym.owner.type.getEnclosingType(); - break; - case BOUND: - recType = tree.getQualifierExpression().type; - break; - case UNBOUND: - recType = samPTypes.head; - samPTypes = samPTypes.tail; - break; - } + //body generation - this can be either a method call or a + //new instance creation expression, depending on the member reference kind + VarSymbol rcvr = addParametersReturnReceiver(); + JCExpression expr = (tree.getMode() == ReferenceMode.INVOKE) + ? expressionInvoke(rcvr) + : expressionNew(); - //generate the parameter list for the bridged member reference - the - //bridge signature will match the signature of the target sam descriptor - - VarSymbol rcvr = (recType == null) - ? null - : addParameter("rec$", recType, false); - - List refPTypes = tree.sym.type.getParameterTypes(); - int refSize = refPTypes.size(); - int samSize = samPTypes.size(); - // Last parameter to copy from referenced method - int last = localContext.needsVarArgsConversion() ? refSize - 1 : refSize; - - List l = refPTypes; - // Use parameter types of the referenced method, excluding final var args - for (int i = 0; l.nonEmpty() && i < last; ++i) { - addParameter("x$" + i, l.head, true); - l = l.tail; - } - // Flatten out the var args - for (int i = last; i < samSize; ++i) { - addParameter("xva$" + i, tree.varargsElement, true); - } - - //generate the bridge method declaration - JCMethodDecl bridgeDecl = make.MethodDef(make.Modifiers(localContext.bridgeSym.flags()), - localContext.bridgeSym.name, - make.QualIdent(samDesc.getReturnType().tsym), - List.nil(), - params.toList(), - tree.sym.type.getThrownTypes() == null - ? List.nil() - : make.Types(tree.sym.type.getThrownTypes()), - null, - null); - bridgeDecl.sym = (MethodSymbol) localContext.bridgeSym; - bridgeDecl.type = localContext.bridgeSym.type = - types.createMethodTypeWithParameters(samDesc, TreeInfo.types(params.toList())); - - //bridge method body generation - this can be either a method call or a - //new instance creation expression, depending on the member reference kind - JCExpression bridgeExpr = (tree.getMode() == ReferenceMode.INVOKE) - ? bridgeExpressionInvoke(makeReceiver(rcvr)) - : bridgeExpressionNew(); - - //the body is either a return expression containing a method call, - //or the method call itself, depending on whether the return type of - //the bridge is non-void/void. - bridgeDecl.body = makeLambdaExpressionBody(bridgeExpr, bridgeDecl); - - return bridgeDecl; + JCLambda slam = make.Lambda(params.toList(), expr); + slam.targets = tree.targets; + slam.type = tree.type; + slam.pos = tree.pos; + return slam; } finally { make.at(prevPos); } } - //where - private JCExpression makeReceiver(VarSymbol rcvr) { - if (rcvr == null) return null; - JCExpression rcvrExpr = make.Ident(rcvr); - Type rcvrType = tree.sym.enclClass().type; - if (rcvrType == syms.arrayClass.type) { - // Map the receiver type to the actually type, not just "array" - rcvrType = tree.getQualifierExpression().type; + + /** + * Generate the parameter list for the converted member reference. + * + * @return The receiver variable symbol, if any + */ + VarSymbol addParametersReturnReceiver() { + Type samDesc = localContext.bridgedRefSig(); + List samPTypes = samDesc.getParameterTypes(); + List descPTypes = tree.getDescriptorType(types).getParameterTypes(); + + // Determine the receiver, if any + VarSymbol rcvr; + switch (tree.kind) { + case BOUND: + // The receiver is explicit in the method reference + rcvr = addParameter("rec$", tree.getQualifierExpression().type, false); + receiverExpression = attr.makeNullCheck(tree.getQualifierExpression()); + break; + case UNBOUND: + // The receiver is the first parameter, extract it and + // adjust the SAM and unerased type lists accordingly + rcvr = addParameter("rec$", samDesc.getParameterTypes().head, false); + samPTypes = samPTypes.tail; + descPTypes = descPTypes.tail; + break; + default: + rcvr = null; + break; + } + List implPTypes = tree.sym.type.getParameterTypes(); + int implSize = implPTypes.size(); + int samSize = samPTypes.size(); + // Last parameter to copy from referenced method, exclude final var args + int last = localContext.needsVarArgsConversion() ? implSize - 1 : implSize; + + // Failsafe -- assure match-up + boolean checkForIntersection = tree.varargsElement != null || implSize == descPTypes.size(); + + // Use parameter types of the implementation method unless the unerased + // SAM parameter type is an intersection type, in that case use the + // erased SAM parameter type so that the supertype relationship + // the implementation method parameters is not obscured. + // Note: in this loop, the lists implPTypes, samPTypes, and descPTypes + // are used as pointers to the current parameter type information + // and are thus not usable afterwards. + for (int i = 0; implPTypes.nonEmpty() && i < last; ++i) { + // By default use the implementation method parmeter type + Type parmType = implPTypes.head; + // If the unerased parameter type is a type variable whose + // bound is an intersection (eg. ) then + // use the SAM parameter type + if (checkForIntersection && descPTypes.head.getKind() == TypeKind.TYPEVAR) { + TypeVar tv = (TypeVar) descPTypes.head; + if (tv.bound.getKind() == TypeKind.INTERSECTION) { + parmType = samPTypes.head; + } } - if (!rcvr.type.tsym.isSubClass(rcvrType.tsym, types)) { - rcvrExpr = make.TypeCast(make.Type(rcvrType), rcvrExpr).setType(rcvrType); - } - return rcvrExpr; + addParameter("x$" + i, parmType, true); + + // Advance to the next parameter + implPTypes = implPTypes.tail; + samPTypes = samPTypes.tail; + descPTypes = descPTypes.tail; + } + // Flatten out the var args + for (int i = last; i < samSize; ++i) { + addParameter("xva$" + i, tree.varargsElement, true); } + return rcvr; + } + + JCExpression getReceiverExpression() { + return receiverExpression; + } + + private JCExpression makeReceiver(VarSymbol rcvr) { + if (rcvr == null) return null; + JCExpression rcvrExpr = make.Ident(rcvr); + Type rcvrType = tree.sym.enclClass().type; + if (rcvrType == syms.arrayClass.type) { + // Map the receiver type to the actually type, not just "array" + rcvrType = tree.getQualifierExpression().type; + } + if (!rcvr.type.tsym.isSubClass(rcvrType.tsym, types)) { + rcvrExpr = make.TypeCast(make.Type(rcvrType), rcvrExpr).setType(rcvrType); + } + return rcvrExpr; + } + /** - * determine the receiver of the bridged method call - the receiver can - * be either the synthetic receiver parameter or a type qualifier; the - * original qualifier expression is never used here, as it might refer - * to symbols not available in the static context of the bridge + * determine the receiver of the method call - the receiver can + * be a type qualifier, the synthetic receiver parameter or 'super'. */ - private JCExpression bridgeExpressionInvoke(JCExpression rcvr) { + private JCExpression expressionInvoke(VarSymbol rcvr) { JCExpression qualifier = tree.sym.isStatic() ? make.Type(tree.sym.owner.type) : (rcvr != null) ? - rcvr : + makeReceiver(rcvr) : tree.getQualifierExpression(); //create the qualifier expression @@ -886,10 +899,9 @@ } /** - * the enclosing expression is either 'null' (no enclosing type) or set - * to the first bridge synthetic parameter + * Lambda body to use for a 'new'. */ - private JCExpression bridgeExpressionNew() { + private JCExpression expressionNew() { if (tree.kind == ReferenceKind.ARRAY_CTOR) { //create the array creation expression JCNewArray newArr = make.NewArray( @@ -899,15 +911,10 @@ newArr.type = tree.getQualifierExpression().type; return newArr; } else { - JCExpression encl = null; - switch (tree.kind) { - case UNBOUND: - case IMPLICIT_INNER: - encl = make.Ident(params.first()); - } - //create the instance creation expression - JCNewClass newClass = make.NewClass(encl, + //note that method reference syntax does not allow an explicit + //enclosing class (so the enclosing class is null) + JCNewClass newClass = make.NewClass(null, List.nil(), make.Type(tree.getQualifierExpression().type), convertArgs(tree.sym, args.toList(), tree.varargsElement), @@ -921,7 +928,8 @@ } private VarSymbol addParameter(String name, Type p, boolean genArg) { - VarSymbol vsym = new VarSymbol(0, names.fromString(name), p, localContext.bridgeSym); + VarSymbol vsym = new VarSymbol(PARAMETER | SYNTHETIC, names.fromString(name), p, owner); + vsym.pos = tree.pos; params.append(make.VarDef(vsym, null)); if (genArg) { args.append(make.Ident(vsym)); @@ -930,15 +938,6 @@ } } - /** - * Bridges a member reference - this is needed when: - * * Var args in the referenced method need to be flattened away - * * super is used - */ - private void bridgeMemberReference(JCMemberReference tree, ReferenceTranslationContext localContext) { - kInfo.addMethod(new MemberReferenceBridger(tree, localContext).bridge()); - } - private MethodType typeToMethodType(Type mt) { Type type = types.erasure(mt); return new MethodType(type.getParameterTypes(), @@ -1258,9 +1257,25 @@ @Override public void visitLambda(JCLambda tree) { + analyzeLambda(tree, "lambda.stat"); + } + + private void analyzeLambda(JCLambda tree, JCExpression methodReferenceReceiver) { + // Translation of the receiver expression must occur first + JCExpression rcvr = translate(methodReferenceReceiver); + LambdaTranslationContext context = analyzeLambda(tree, "mref.stat.1"); + if (rcvr != null) { + context.methodReferenceReceiver = rcvr; + } + } + + private LambdaTranslationContext analyzeLambda(JCLambda tree, String statKey) { List prevStack = frameStack; try { - LambdaTranslationContext context = (LambdaTranslationContext)makeLambdaContext(tree); + LambdaTranslationContext context = new LambdaTranslationContext(tree); + if (dumpLambdaToMethodStats) { + log.note(tree, statKey, context.needsAltMetafactory(), context.translatedSym); + } frameStack = frameStack.prepend(new Frame(tree)); for (JCVariableDecl param : tree.params) { context.addSymbol(param.sym, PARAM); @@ -1269,6 +1284,7 @@ contextMap.put(tree, context); super.visitLambda(tree); context.complete(); + return context; } finally { frameStack = prevStack; @@ -1357,47 +1373,24 @@ * information added in the LambdaToMethod pass will have the wrong * signature. Hooks between Lower and LambdaToMethod have been added to * handle normal "new" in this case. This visitor converts potentially - * effected method references into a lambda containing a normal "new" of - * the class. + * affected method references into a lambda containing a normal + * expression. * * @param tree */ @Override public void visitReference(JCMemberReference tree) { - if (tree.getMode() == ReferenceMode.NEW - && tree.kind != ReferenceKind.ARRAY_CTOR - && tree.sym.owner.isLocal()) { - MethodSymbol consSym = (MethodSymbol) tree.sym; - List ptypes = ((MethodType) consSym.type).getParameterTypes(); - Type classType = consSym.owner.type; - - // Build lambda parameters - // partially cloned from TreeMaker.Params until 8014021 is fixed - Symbol owner = owner(); - ListBuffer paramBuff = new ListBuffer(); - int i = 0; - for (List l = ptypes; l.nonEmpty(); l = l.tail) { - JCVariableDecl param = make.Param(make.paramName(i++), l.head, owner); - param.sym.pos = tree.pos; - paramBuff.append(param); - } - List params = paramBuff.toList(); - - // Make new-class call - JCNewClass nc = makeNewClass(classType, make.Idents(params)); - nc.pos = tree.pos; - - // Make lambda holding the new-class call - JCLambda slam = make.Lambda(params, nc); - slam.targets = tree.targets; - slam.type = tree.type; - slam.pos = tree.pos; - - // Now it is a lambda, process as such - visitLambda(slam); + ReferenceTranslationContext rcontext = new ReferenceTranslationContext(tree); + contextMap.put(tree, rcontext); + if (rcontext.needsConversionToLambda()) { + // Convert to a lambda, and process as such + MemberReferenceToLambda conv = new MemberReferenceToLambda(tree, rcontext, owner()); + analyzeLambda(conv.lambda(), conv.getReceiverExpression()); } else { super.visitReference(tree); - contextMap.put(tree, makeReferenceContext(tree)); + if (dumpLambdaToMethodStats) { + log.note(tree, "mref.stat", rcontext.needsAltMetafactory(), null); + } } } @@ -1652,14 +1645,6 @@ } } - private TranslationContext makeLambdaContext(JCLambda tree) { - return new LambdaTranslationContext(tree); - } - - private TranslationContext makeReferenceContext(JCMemberReference tree) { - return new ReferenceTranslationContext(tree); - } - private class Frame { final JCTree tree; List locals; @@ -1779,6 +1764,13 @@ */ final Set freeVarProcessedLocalClasses; + /** + * For method references converted to lambdas. The method + * reference receiver expression. Must be treated like a captured + * variable. + */ + JCExpression methodReferenceReceiver; + LambdaTranslationContext(JCLambda tree) { super(tree); Frame frame = frameStack.head; @@ -1798,9 +1790,6 @@ // This symbol will be filled-in in complete this.translatedSym = makePrivateSyntheticMethod(0, null, null, owner.enclClass()); - if (dumpLambdaToMethodStats) { - log.note(tree, "lambda.stat", needsAltMetafactory(), translatedSym); - } translatedSymbols = new EnumMap<>(LambdaSymbolKind.class); translatedSymbols.put(PARAM, new LinkedHashMap()); @@ -2017,6 +2006,13 @@ for (Symbol thisSym : getSymbolMap(CAPTURED_VAR).values()) { params.append(make.VarDef((VarSymbol) thisSym, null)); } + if (methodReferenceReceiver != null) { + params.append(make.VarDef( + make.Modifiers(PARAMETER|FINAL), + names.fromString("$rcvr$"), + make.Type(methodReferenceReceiver.type), + null)); + } for (Symbol thisSym : getSymbolMap(PARAM).values()) { params.append(make.VarDef((VarSymbol) thisSym, null)); } @@ -2044,40 +2040,27 @@ * and the used by the main translation routines in order to adjust method * references (i.e. in case a bridge is needed) */ - private class ReferenceTranslationContext extends TranslationContext { + private final class ReferenceTranslationContext extends TranslationContext { final boolean isSuper; - final Symbol bridgeSym; final Symbol sigPolySym; ReferenceTranslationContext(JCMemberReference tree) { super(tree); this.isSuper = tree.hasKind(ReferenceKind.SUPER); - this.bridgeSym = needsBridge() - ? makePrivateSyntheticMethod(isSuper ? 0 : STATIC, - referenceBridgeName(), null, - owner.enclClass()) - : null; this.sigPolySym = isSignaturePolymorphic() ? makePrivateSyntheticMethod(tree.sym.flags(), tree.sym.name, bridgedRefSig(), tree.sym.enclClass()) : null; - if (dumpLambdaToMethodStats) { - String key = bridgeSym == null ? - "mref.stat" : "mref.stat.1"; - log.note(tree, key, needsAltMetafactory(), bridgeSym); - } } /** * Get the opcode associated with this method reference */ int referenceKind() { - return LambdaToMethod.this.referenceKind(needsBridge() - ? bridgeSym - : tree.sym); + return LambdaToMethod.this.referenceKind(tree.sym); } boolean needsVarArgsConversion() { @@ -2085,62 +2068,6 @@ } /** - * Generate a disambiguating string to increase stability (important - * if serialized) - * - * @return String to differentiate synthetic lambda method names - */ - private String referenceBridgeDisambiguation() { - StringBuilder buf = new StringBuilder(); - // Append the enclosing method signature to differentiate - // overloaded enclosing methods. - if (owner.type != null) { - buf.append(typeSig(owner.type)); - buf.append(":"); - } - - // Append qualifier type - buf.append(classSig(tree.sym.owner.type)); - - // Note static/instance - buf.append(tree.sym.isStatic()? " S " : " I "); - - // Append referenced signature - buf.append(typeSig(tree.sym.erasure(types))); - - return buf.toString(); - } - - /** - * Construct a unique stable name for the method reference bridge - * - * @return Name to use for the synthetic method name - */ - private Name referenceBridgeName() { - StringBuilder buf = new StringBuilder(); - // Append lambda ID, this is semantically significant - buf.append(names.lambda); - // Note that it is a method reference bridge - buf.append("MR$"); - // Append the enclosing method name - buf.append(enclosingMethodName()); - buf.append('$'); - // Append the referenced method name - buf.append(syntheticMethodNameComponent(tree.sym.name)); - buf.append('$'); - // Append a hash of the disambiguating string : enclosing method - // signature, etc. - String disam = referenceBridgeDisambiguation(); - buf.append(Integer.toHexString(disam.hashCode())); - buf.append('$'); - // The above appended name components may not be unique, append - // a count based on the above name components. - buf.append(syntheticMethodNameCounts.getIndex(buf)); - String result = buf.toString(); - return names.fromString(result); - } - - /** * @return Is this an array operation like clone() */ boolean isArrayOp() { @@ -2175,13 +2102,40 @@ } /** - * Does this reference needs a bridge (i.e. var args need to be - * expanded or "super" is used) + * Erasure destroys the implementation parameter subtype + * relationship for intersection types */ - final boolean needsBridge() { - return isSuper || needsVarArgsConversion() || isArrayOp() || + boolean interfaceParameterIsIntersectionType() { + List tl = tree.getDescriptorType(types).getParameterTypes(); + if (tree.kind == ReferenceKind.UNBOUND) { + tl = tl.tail; + } + for (; tl.nonEmpty(); tl = tl.tail) { + Type pt = tl.head; + if (pt.getKind() == TypeKind.TYPEVAR) { + TypeVar tv = (TypeVar) pt; + if (tv.bound.getKind() == TypeKind.INTERSECTION) { + return true; + } + } + } + return false; + } + + /** + * Does this reference need to be converted to a lambda + * (i.e. var args need to be expanded or "super" is used) + */ + final boolean needsConversionToLambda() { + return interfaceParameterIsIntersectionType() || + isSuper || + needsVarArgsConversion() || + isArrayOp() || isPrivateInOtherClass() || - !receiverAccessible(); + !receiverAccessible() || + (tree.getMode() == ReferenceMode.NEW && + tree.kind != ReferenceKind.ARRAY_CTOR && + (tree.sym.owner.isLocal() || tree.sym.owner.isInner())); } Type generatedRefSig() { diff -r d4c7822e9d64 -r 244e6dc77287 src/share/classes/com/sun/tools/javac/comp/Lower.java --- a/src/share/classes/com/sun/tools/javac/comp/Lower.java Mon Dec 01 11:39:34 2014 -0800 +++ b/src/share/classes/com/sun/tools/javac/comp/Lower.java Fri Dec 12 14:57:02 2014 -0800 @@ -2716,9 +2716,10 @@ syms.intType, tree.sym); ordParam.mods.flags |= SYNTHETIC; ordParam.sym.flags_field |= SYNTHETIC; + MethodSymbol m = tree.sym; tree.params = tree.params.prepend(ordParam).prepend(nameParam); - - MethodSymbol m = tree.sym; + incrementParamTypeAnnoIndexes(m, 2); + m.extraParams = m.extraParams.prepend(ordParam.sym); m.extraParams = m.extraParams.prepend(nameParam.sym); Type olderasure = m.erasure(types); @@ -2741,6 +2742,17 @@ } } //where + private void incrementParamTypeAnnoIndexes(MethodSymbol m, + int amount) { + for (final Attribute.TypeCompound anno : m.getRawTypeAttributes()) { + // Increment the parameter_index of any existing formal + // parameter annotations. + if (anno.position.type == TargetType.METHOD_FORMAL_PARAMETER) { + anno.position.parameter_index += amount; + } + } + } + private void visitMethodDefInternal(JCMethodDecl tree) { if (tree.name == names.init && (currentClass.isInner() || currentClass.isLocal())) { @@ -2771,8 +2783,10 @@ // Add this$n (if needed) in front of and free variables behind // constructor parameter list. tree.params = tree.params.appendList(fvdefs); - if (currentClass.hasOuterInstance()) + if (currentClass.hasOuterInstance()) { tree.params = tree.params.prepend(otdef); + incrementParamTypeAnnoIndexes(m, 1); + } // If this is an initial constructor, i.e., it does not start with // this(...), insert initializers for this$n and proxies diff -r d4c7822e9d64 -r 244e6dc77287 src/share/classes/com/sun/tools/javac/comp/Resolve.java --- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java Mon Dec 01 11:39:34 2014 -0800 +++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java Fri Dec 12 14:57:02 2014 -0800 @@ -3220,7 +3220,7 @@ super(referenceTree, name, site, argtypes.tail, typeargtypes, maxPhase); if (site.isRaw() && !argtypes.head.hasTag(NONE)) { Type asSuperSite = types.asSuper(argtypes.head, site.tsym); - this.site = asSuperSite; + this.site = types.capture(asSuperSite); } } diff -r d4c7822e9d64 -r 244e6dc77287 src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java --- a/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java Mon Dec 01 11:39:34 2014 -0800 +++ b/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java Fri Dec 12 14:57:02 2014 -0800 @@ -670,6 +670,27 @@ } + private void writeParamAnnotations(List params, + RetentionPolicy retention) { + for (VarSymbol s : params) { + ListBuffer buf = new ListBuffer<>(); + for (Attribute.Compound a : s.getRawAttributes()) + if (types.getRetention(a) == retention) + buf.append(a); + databuf.appendChar(buf.length()); + for (Attribute.Compound a : buf) + writeCompoundAttribute(a); + } + + } + + private void writeParamAnnotations(MethodSymbol m, + RetentionPolicy retention) { + databuf.appendByte(m.params.length() + m.extraParams.length()); + writeParamAnnotations(m.extraParams, retention); + writeParamAnnotations(m.params, retention); + } + /** Write method parameter annotations; * return number of attributes written. */ @@ -692,31 +713,13 @@ int attrCount = 0; if (hasVisible) { int attrIndex = writeAttr(names.RuntimeVisibleParameterAnnotations); - databuf.appendByte(m.params.length()); - for (VarSymbol s : m.params) { - ListBuffer buf = new ListBuffer(); - for (Attribute.Compound a : s.getRawAttributes()) - if (types.getRetention(a) == RetentionPolicy.RUNTIME) - buf.append(a); - databuf.appendChar(buf.length()); - for (Attribute.Compound a : buf) - writeCompoundAttribute(a); - } + writeParamAnnotations(m, RetentionPolicy.RUNTIME); endAttr(attrIndex); attrCount++; } if (hasInvisible) { int attrIndex = writeAttr(names.RuntimeInvisibleParameterAnnotations); - databuf.appendByte(m.params.length()); - for (VarSymbol s : m.params) { - ListBuffer buf = new ListBuffer(); - for (Attribute.Compound a : s.getRawAttributes()) - if (types.getRetention(a) == RetentionPolicy.CLASS) - buf.append(a); - databuf.appendChar(buf.length()); - for (Attribute.Compound a : buf) - writeCompoundAttribute(a); - } + writeParamAnnotations(m, RetentionPolicy.CLASS); endAttr(attrIndex); attrCount++; } diff -r d4c7822e9d64 -r 244e6dc77287 test/lib/annotations/annotations/classfile/ClassfileInspector.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/lib/annotations/annotations/classfile/ClassfileInspector.java Fri Dec 12 14:57:02 2014 -0800 @@ -0,0 +1,1733 @@ +/* + * Copyright (c) 2012, 2014, 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. + */ + +package annotations.classfile; + +import java.io.*; +import java.net.URL; +import java.util.List; + +import com.sun.tools.classfile.*; + +/** + * A class providing utilities for writing tests that inspect class + * files directly, looking for specific type annotations. + * + * Note: this framework does not currently handle repeating + * annotations. + */ +public class ClassfileInspector { + + /** + * A group of expected annotations to be found in a given class. + * If the class name is null, then the template will be applied to + * every class. + */ + public static class Expected { + /** + * The name of the class. If {@code null} this template will + * apply to every class; otherwise, it will only be applied to + * the named class. + */ + public final String classname; + + /** + * The expected class annotations. These will be checked + * against the class' attributes. + */ + public final ExpectedAnnotation[] classAnnos; + + /** + * The expected method annotations. These will be checked + * against all methods in the class. + */ + public final ExpectedMethodAnnotation[] methodAnnos; + + /** + * The expected method parameter annotations. These will be checked + * against all methods in the class. + */ + public final ExpectedParameterAnnotation[] methodParamAnnos; + + /** + * The expected field type annotations. These will be checked + * against all fields in the class. + */ + public final ExpectedFieldAnnotation[] fieldAnnos; + + /** + * The expected class type annotations. These will be checked + * against the class' attributes. + */ + public final ExpectedTypeAnnotation[] classTypeAnnos; + + /** + * The expected method type annotations. These will be checked + * against all methods in the class. + */ + public final ExpectedMethodTypeAnnotation[] methodTypeAnnos; + + /** + * The expected field type annotations. These will be checked + * against all fields in the class. + */ + public final ExpectedFieldTypeAnnotation[] fieldTypeAnnos; + + /** + * Create an {@code Expected} from all components. + * + * @param classname The name of the class to match, or {@code + * null} for all classes. + * @param classAnnos The expected class annotations. + * @param methodAnnos The expected method annotations. + * @param methodParamAnnos The expected method parameter annotations. + * @param fieldAnnos The expected field annotations. + * @param classTypeAnnos The expected class type annotations. + * @param methodTypeAnnos The expected method type annotations. + * @param fieldTypeAnnos The expected field type annotations. + */ + public Expected(String classname, + ExpectedAnnotation[] classAnnos, + ExpectedMethodAnnotation[] methodAnnos, + ExpectedParameterAnnotation[] methodParamAnnos, + ExpectedFieldAnnotation[] fieldAnnos, + ExpectedTypeAnnotation[] classTypeAnnos, + ExpectedMethodTypeAnnotation[] methodTypeAnnos, + ExpectedFieldTypeAnnotation[] fieldTypeAnnos) { + this.classname = classname; + this.classAnnos = classAnnos; + this.methodAnnos = methodAnnos; + this.methodParamAnnos = methodParamAnnos; + this.fieldAnnos = fieldAnnos; + this.classTypeAnnos = classTypeAnnos; + this.methodTypeAnnos = methodTypeAnnos; + this.fieldTypeAnnos = fieldTypeAnnos; + } + + /** + * Create an {@code Expected} from regular annotation components. + * + * @param classname The name of the class to match, or {@code + * null} for all classes. + * @param classAnnos The expected class annotations. + * @param methodAnnos The expected method annotations. + * @param methodParamAnnos The expected method parameter annotations. + * @param fieldAnnos The expected field annotations. + */ + public Expected(String classname, + ExpectedAnnotation[] classAnnos, + ExpectedMethodAnnotation[] methodAnnos, + ExpectedParameterAnnotation[] methodParamAnnos, + ExpectedFieldAnnotation[] fieldAnnos) { + this(classname, classAnnos, methodAnnos, methodParamAnnos, + fieldAnnos, null, null, null); + } + + /** + * Create an {@code Expected} from type annotation components. + * + * @param classname The name of the class to match, or {@code + * null} for all classes. + * @param classTypeAnnos The expected class type annotations. + * @param methodTypeAnnos The expected method type annotations. + * @param fieldTypeAnnos The expected field type annotations. + */ + public Expected(String classname, + ExpectedTypeAnnotation[] classTypeAnnos, + ExpectedMethodTypeAnnotation[] methodTypeAnnos, + ExpectedFieldTypeAnnotation[] fieldTypeAnnos) { + this(classname, null, null, null, null, + classTypeAnnos, methodTypeAnnos, fieldTypeAnnos); + } + + public String toString() { + final StringBuilder sb = new StringBuilder(); + final String newline = System.lineSeparator(); + sb.append("Expected on class ").append(classname); + if (null != classAnnos) { + sb.append(newline).append("Class annotations:").append(newline); + for(ExpectedAnnotation anno : classAnnos) { + sb.append(anno).append(newline); + } + } + if (null != methodAnnos) { + sb.append(newline).append("Method annotations:").append(newline); + for(ExpectedAnnotation anno : methodAnnos) { + sb.append(anno).append(newline); + } + } + if (null != methodParamAnnos) { + sb.append(newline).append("Method param annotations:").append(newline); + for(ExpectedAnnotation anno : methodParamAnnos) { + sb.append(anno).append(newline); + } + } + if (null != fieldAnnos) { + sb.append(newline).append("Field annotations:").append(newline); + for(ExpectedAnnotation anno : fieldAnnos) { + sb.append(anno).append(newline); + } + } + if (null != classTypeAnnos) { + sb.append(newline).append("Class type annotations:").append(newline); + for(ExpectedAnnotation anno : classTypeAnnos) { + sb.append(anno).append(newline); + } + } + if (null != methodTypeAnnos) { + sb.append(newline).append("Method type annotations:").append(newline); + for(ExpectedAnnotation anno : methodTypeAnnos) { + sb.append(anno).append(newline); + } + } + if (null != fieldTypeAnnos) { + sb.append(newline).append("Field type annotations:").append(newline); + for(ExpectedAnnotation anno : fieldTypeAnnos) { + sb.append(anno).append(newline); + } + } + return sb.toString(); + } + + /** + * See if this template applies to a class. + * + * @param classname The classname to check. + * @return Whether or not this template should apply. + */ + public boolean matchClassName(String classname) { + return this.classname == null || this.classname.equals(classname); + } + + /** + * After applying the template to all classes, check to see if + * any of the expected annotations weren't matched. + * + * @return The number of missed matches. + */ + public int check() { + int count = 0; + if (classAnnos != null) { + for(ExpectedAnnotation expected : classAnnos) { + if (!expected.check()) { + count++; + } + } + } + if (methodAnnos != null) { + for(ExpectedAnnotation expected : methodAnnos) { + if (!expected.check()) { + count++; + } + } + } + if (methodParamAnnos != null) { + for(ExpectedAnnotation expected : methodParamAnnos) { + if (!expected.check()) { + count++; + } + } + } + if (fieldAnnos != null) { + for(ExpectedAnnotation expected : fieldAnnos) { + if (!expected.check()) { + count++; + } + } + } + if (classTypeAnnos != null) { + for(ExpectedAnnotation expected : classTypeAnnos) { + if (!expected.check()) { + count++; + } + } + } + if (methodTypeAnnos != null) { + for(ExpectedAnnotation expected : methodTypeAnnos) { + if (!expected.check()) { + count++; + } + } + } + if (fieldTypeAnnos != null) { + for(ExpectedAnnotation expected : fieldTypeAnnos) { + if (!expected.check()) { + count++; + } + } + } + return count; + } + } + + /** + * An expected annotation. This is both a superclass for + * method, field, and type annotations, as well as a class for + * annotations on a class. + */ + public static class ExpectedAnnotation { + protected int count = 0; + protected final String expectedName; + protected final int expectedCount; + protected final boolean visibility; + + /** + * Create an {@code ExpectedAnnotation} from its + * components. It is usually a better idea to use a {@code + * Builder} to do this. + * + * @param expectedName The expected annotation name. + * @param visibility Whether this annotation should be runtime-visible. + * @param expectedCount The number of annotations that should + * be seen. If 0, this asserts that the + * described annotation is not present. + */ + public ExpectedAnnotation(String expectedName, + boolean visibility, + int expectedCount) { + this.expectedName = expectedName; + this.visibility = visibility; + this.expectedCount = expectedCount; + } + + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append("Expected "); + sb.append(expectedCount); + sb.append(" annotation "); + sb.append(expectedName); + sb.append(visibility ? ", runtime visibile " : ", runtime invisibile "); + return sb.toString(); + } + + /** + * See if this template matches the given visibility. + * + * @param Whether or not the annotation is visible at runtime. + * @return Whether or not this template matches the visibility. + */ + public boolean matchVisibility(boolean visibility) { + return this.visibility == visibility; + } + + /** + * Attempty to match this template against an annotation. If + * it does match, then the match count for the template will + * be incremented. Otherwise, nothing will be done. + * + * @param anno The annotation to attempt to match. + */ + public void matchAnnotation(ConstantPool cpool, + Annotation anno) { + if (checkMatch(cpool, anno)) { + count++; + } + } + + /** + * Indicate whether an annotation matches this expected + * annotation. + * + * @param ConstantPool The constant pool to use. + * @param anno The annotation to check. + * @return Whether the annotation matches. + */ + protected boolean checkMatch(ConstantPool cpool, + Annotation anno) { + try { + return cpool.getUTF8Info(anno.type_index).value.equals("L" + expectedName + ";"); + } catch(Exception e) { + return false; + } + } + + /** + * After all matching, check to see if the expected number of + * matches equals the actual number. If not, then print a + * failure message and return {@code false}. + * + * @return Whether or not the expected number of matched + * equals the actual number. + */ + public boolean check() { + if (count != expectedCount) { + System.err.println(this + ", but saw " + count); + return false; + } else { + return true; + } + } + } + + /** + * An annotation found on a method. + */ + public static class ExpectedMethodAnnotation extends ExpectedAnnotation { + protected final String methodname; + + /** + * Create an {@code ExpectedMethodAnnotation} from its + * components. It is usually a better idea to use a {@code + * Builder} to do this. + * + * @param methodname The expected method name. + * @param expectedName The expected annotation name. + * @param visibility Whether this annotation should be runtime-visible. + * @param expectedCount The number of annotations that should be seen. + */ + public ExpectedMethodAnnotation(String methodname, + String expectedName, + boolean visibility, + int expectedCount) { + super(expectedName, visibility, expectedCount); + this.methodname = methodname; + } + + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append("Expected "); + sb.append(expectedCount); + sb.append(" annotation "); + sb.append(expectedName); + sb.append(visibility ? ", runtime visibile " : ", runtime invisibile "); + sb.append(" on method "); + sb.append(methodname); + return sb.toString(); + } + + /** + * See if this template applies to a method. + * + * @param methodname The method name to check. + * @return Whether or not this template should apply. + */ + public boolean matchMethodName(String methodname) { + return this.methodname.equals(methodname); + } + + } + + /** + * An annotation found on a method parameter. + */ + public static class ExpectedParameterAnnotation + extends ExpectedMethodAnnotation { + protected final int index; + + /** + * Create an {@code ExpectedParameterAnnotation} from its + * components. It is usually a better idea to use a {@code + * Builder} to do this. + * + * @param methodname The expected method name. + * @param index The parameter index. + * @param expectedName The expected annotation name. + * @param visibility Whether this annotation should be runtime-visible. + * @param expectedCount The number of annotations that should be seen. + */ + public ExpectedParameterAnnotation(String methodname, + int index, + String expectedName, + boolean visibility, + int expectedCount) { + super(methodname, expectedName, visibility, expectedCount); + this.index = index; + } + + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append("Expected "); + sb.append(expectedCount); + sb.append(" annotation "); + sb.append(expectedName); + sb.append(visibility ? ", runtime visibile " : ", runtime invisibile "); + sb.append(" on method "); + sb.append(methodname); + sb.append(" parameter " + index); + return sb.toString(); + } + + } + + /** + * An annotation found on a field. + */ + public static class ExpectedFieldAnnotation extends ExpectedAnnotation { + private final String fieldname; + + /** + * Create an {@code ExpectedFieldAnnotation} from its + * components. It is usually a better idea to use a {@code + * Builder} to do this. + * + * @param fieldname The expected field name. + * @param expectedName The expected annotation name. + * @param visibility Whether this annotation should be runtime-visible. + * @param expectedCount The number of annotations that should be seen. + */ + public ExpectedFieldAnnotation(String fieldname, + String expectedName, + boolean visibility, + int expectedCount) { + super(expectedName, visibility, expectedCount); + this.fieldname = fieldname; + } + + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append("Expected ").append(expectedCount) + .append(" annotation ").append(expectedName) + .append(visibility ? ", runtime visibile " : ", runtime invisibile ") + .append(" on field ").append(fieldname); + return sb.toString(); + } + + /** + * See if this template applies to a field. + * + * @param fieldname The field name to check. + * @return Whether or not this template should apply. + */ + public boolean matchFieldName(String fieldname) { + return this.fieldname.equals(fieldname); + } + + } + + /** + * An expected type annotation. This is both a superclass for + * method and field type annotations, as well as a class for type + * annotations on a class. + */ + public static class ExpectedTypeAnnotation extends ExpectedAnnotation { + protected final TypeAnnotation.TargetType targetType; + protected final int bound_index; + protected final int parameter_index; + protected final int type_index; + protected final int exception_index; + protected final TypeAnnotation.Position.TypePathEntry[] typePath; + + /** + * Create an {@code ExpectedTypeAnnotation} from its + * components. It is usually a better idea to use a {@code + * Builder} to do this. + * + * @param expectedName The expected annotation name. + * @param visibility Whether this annotation should be runtime-visible. + * @param expectedCount The number of annotations that should + * be seen. If 0, this asserts that the + * described annotation is not present. + * @param targetType The expected target type. + * @param bound_index The expected bound index, or {@code Integer.MIN_VALUE}. + * @param parameter_index The expected parameter index, or + * {@code Integer.MIN_VALUE}. + * @param type_index The expected type index, or {@code Integer.MIN_VALUE}. + * @param exception_index The expected exception index, or + * {@code Integer.MIN_VALUE}. + * @param typePath The expected type path. + */ + public ExpectedTypeAnnotation(String expectedName, + boolean visibility, + int expectedCount, + TypeAnnotation.TargetType targetType, + int bound_index, + int parameter_index, + int type_index, + int exception_index, + TypeAnnotation.Position.TypePathEntry... typePath) { + super(expectedName, visibility, expectedCount); + this.targetType = targetType; + this.bound_index = bound_index; + this.parameter_index = parameter_index; + this.type_index = type_index; + this.exception_index = exception_index; + this.typePath = typePath; + } + + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append("Expected "); + sb.append(expectedCount); + sb.append(" annotation "); + sb.append(expectedName); + sb.append(visibility ? ", runtime visibile " : ", runtime invisibile "); + sb.append(targetType); + sb.append(", bound_index = "); + sb.append(bound_index); + sb.append(", parameter_index = "); + sb.append(parameter_index); + sb.append(", type_index = "); + sb.append(type_index); + sb.append(", exception_index = "); + sb.append(exception_index); + sb.append(", type_path = ["); + for(int i = 0; i < typePath.length; i++) { + if (i != 0) { + sb.append(", "); + } + sb.append(typePath[i]); + } + sb.append("]"); + return sb.toString(); + } + + @Override + public void matchAnnotation(ConstantPool cpool, + Annotation anno) {} + + public void matchAnnotation(TypeAnnotation anno) { + if (checkMatch(anno)) { + count++; + } + } + + public boolean checkMatch(TypeAnnotation anno) { + boolean matches = checkMatch(anno.constant_pool, anno.annotation); + + matches = matches && anno.position.type == targetType; + matches = matches && anno.position.bound_index == bound_index; + matches = matches && anno.position.parameter_index == parameter_index; + matches = matches && anno.position.type_index == type_index; + matches = matches && anno.position.exception_index == exception_index; + matches = matches && anno.position.location.size() == typePath.length; + + if (matches) { + int i = 0; + for(TypeAnnotation.Position.TypePathEntry entry : + anno.position.location) { + matches = matches && typePath[i++].equals(entry); + } + } + + return matches; + } + + /** + * A builder class for creating {@code + * ExpectedTypeAnnotation}s in a more convenient fashion. The + * constructor for {@code ExpectedTypeAnnotation} takes a + * large number of parameters (by necessity). This class + * allows users to construct a {@code ExpectedTypeAnnotation}s + * using only the ones they need. + */ + public static class Builder { + protected final String expectedName; + protected final boolean visibility; + protected final int expectedCount; + protected final TypeAnnotation.TargetType targetType; + protected int bound_index = Integer.MIN_VALUE; + protected int parameter_index = Integer.MIN_VALUE; + protected int type_index = Integer.MIN_VALUE; + protected int exception_index = Integer.MIN_VALUE; + protected TypeAnnotation.Position.TypePathEntry[] typePath = + new TypeAnnotation.Position.TypePathEntry[0]; + + /** + * Create a {@code Builder} from the mandatory parameters. + * + * @param expectedName The expected annotation name. + * @param targetType The expected target type. + * @param visibility Whether this annotation should be runtime-visible. + * @param expectedCount The number of annotations that should be seen. + */ + public Builder(String expectedName, + TypeAnnotation.TargetType targetType, + boolean visibility, + int expectedCount) { + this.expectedName = expectedName; + this.visibility = visibility; + this.expectedCount = expectedCount; + this.targetType = targetType; + } + + /** + * Create an {@code ExpectedTypeAnnotation} from all + * parameters that have been provided. The default values + * will be used for those that have not. + * + * @return The cretaed {@code ExpectedTypeAnnotation}. + */ + public ExpectedTypeAnnotation build() { + return new ExpectedTypeAnnotation(expectedName, visibility, + expectedCount, targetType, + bound_index, parameter_index, + type_index, exception_index, + typePath); + } + + /** + * Provide a bound index parameter. + * + * @param bound_index The bound_index value. + */ + public Builder setBoundIndex(int bound_index) { + this.bound_index = bound_index; + return this; + } + + /** + * Provide a parameter index parameter. + * + * @param bound_index The parameter_index value. + */ + public Builder setParameterIndex(int parameter_index) { + this.parameter_index = parameter_index; + return this; + } + + /** + * Provide a type index parameter. + * + * @param type_index The type_index value. + */ + public Builder setTypeIndex(int type_index) { + this.type_index = type_index; + return this; + } + + /** + * Provide an exception index parameter. + * + * @param exception_index The exception_index value. + */ + public Builder setExceptionIndex(int exception_index) { + this.exception_index = exception_index; + return this; + } + + /** + * Provide a type path parameter. + * + * @param typePath The type path value. + */ + public Builder setTypePath(TypeAnnotation.Position.TypePathEntry[] typePath) { + this.typePath = typePath; + return this; + } + } + } + + /** + * A type annotation found on a method. + */ + public static class ExpectedMethodTypeAnnotation extends ExpectedTypeAnnotation { + private final String methodname; + + /** + * Create an {@code ExpectedMethodTypeAnnotation} from its + * components. It is usually a better idea to use a {@code + * Builder} to do this. + * + * @param methodname The expected method name. + * @param expectedName The expected annotation name. + * @param visibility Whether this annotation should be runtime-visible. + * @param expectedCount The number of annotations that should be seen. + * @param targetType The expected target type. + * @param bound_index The expected bound index, or {@code Integer.MIN_VALUE}. + * @param parameter_index The expected parameter index, or + * {@code Integer.MIN_VALUE}. + * @param type_index The expected type index, or {@code Integer.MIN_VALUE}. + * @param exception_index The expected exception index, or + * {@code Integer.MIN_VALUE}. + * @param typePath The expected type path. + */ + public ExpectedMethodTypeAnnotation(String methodname, + String expectedName, + boolean visibility, + int expectedCount, + TypeAnnotation.TargetType targetType, + int bound_index, + int parameter_index, + int type_index, + int exception_index, + TypeAnnotation.Position.TypePathEntry... typePath) { + super(expectedName, visibility, expectedCount, targetType, bound_index, + parameter_index, type_index, exception_index, typePath); + this.methodname = methodname; + } + + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append("Expected "); + sb.append(expectedCount); + sb.append(" annotation "); + sb.append(expectedName); + sb.append(visibility ? ", runtime visibile " : ", runtime invisibile "); + sb.append(targetType); + sb.append(", bound_index = "); + sb.append(bound_index); + sb.append(", parameter_index = "); + sb.append(parameter_index); + sb.append(", type_index = "); + sb.append(type_index); + sb.append(", exception_index = "); + sb.append(exception_index); + sb.append(", type_path = ["); + for(int i = 0; i < typePath.length; i++) { + if (i != 0) { + sb.append(", "); + } + sb.append(typePath[i]); + } + sb.append("]"); + sb.append(" on method "); + sb.append(methodname); + return sb.toString(); + } + + /** + * See if this template applies to a method. + * + * @param methodname The method name to check. + * @return Whether or not this template should apply. + */ + public boolean matchMethodName(String methodname) { + return this.methodname.equals(methodname); + } + + /** + * A builder class for creating {@code + * ExpectedMethodTypeAnnotation}s in a more convenient fashion. The + * constructor for {@code ExpectedMethodTypeAnnotation} takes a + * large number of parameters (by necessity). This class + * allows users to construct a {@code ExpectedMethodTypeAnnotation}s + * using only the ones they need. + */ + public static class Builder extends ExpectedTypeAnnotation.Builder { + protected final String methodname; + + /** + * Create a {@code Builder} from the mandatory parameters. + * + * @param methodname The expected method name. + * @param expectedName The expected annotation name. + * @param targetType The expected target type. + * @param visibility Whether this annotation should be runtime-visible. + * @param expectedCount The number of annotations that should be seen. + */ + public Builder(String methodname, + String expectedName, + TypeAnnotation.TargetType targetType, + boolean visibility, + int expectedCount) { + super(expectedName, targetType, visibility, expectedCount); + this.methodname = methodname; + } + + /** + * Create an {@code ExpectedMethodTypeAnnotation} from all + * parameters that have been provided. The default values + * will be used for those that have not. + * + * @return The cretaed {@code ExpectedMethodTypeAnnotation}. + */ + public ExpectedMethodTypeAnnotation build() { + return new ExpectedMethodTypeAnnotation(methodname, expectedName, + visibility, expectedCount, + targetType, bound_index, + parameter_index, type_index, + exception_index, typePath); + } + } + } + + /** + * A type annotation found on a field. + */ + public static class ExpectedFieldTypeAnnotation extends ExpectedTypeAnnotation { + private final String fieldname; + + /** + * Create an {@code ExpectedFieldTypeAnnotation} from its + * components. It is usually a better idea to use a {@code + * Builder} to do this. + * + * @param fieldname The expected field name. + * @param expectedName The expected annotation name. + * @param visibility Whether this annotation should be runtime-visible. + * @param expectedCount The number of annotations that should be seen. + * @param targetType The expected target type. + * @param bound_index The expected bound index, or {@code Integer.MIN_VALUE}. + * @param parameter_index The expected parameter index, or + * {@code Integer.MIN_VALUE}. + * @param type_index The expected type index, or {@code Integer.MIN_VALUE}. + * @param exception_index The expected exception index, or + * {@code Integer.MIN_VALUE}. + * @param typePath The expected type path. + */ + public ExpectedFieldTypeAnnotation(String fieldname, + String expectedName, + boolean visibility, + int expectedCount, + TypeAnnotation.TargetType targetType, + int bound_index, + int parameter_index, + int type_index, + int exception_index, + TypeAnnotation.Position.TypePathEntry... typePath) { + super(expectedName, visibility, expectedCount, targetType, bound_index, + parameter_index, type_index, exception_index, typePath); + this.fieldname = fieldname; + } + + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append("Expected ").append(expectedCount) + .append(" annotation ").append(expectedName) + .append(visibility ? ", runtime visibile " : ", runtime invisibile ") + .append(targetType) + .append(", bound_index = ").append(bound_index) + .append(", parameter_index = ").append(parameter_index) + .append(", type_index = ").append(type_index) + .append(", exception_index = ").append(exception_index) + .append(", type_path = ["); + + for(int i = 0; i < typePath.length; i++) { + if (i != 0) { + sb.append(", "); + } + sb.append(typePath[i]); + } + sb.append("]") + .append(" on field ").append(fieldname); + return sb.toString(); + } + + /** + * See if this template applies to a field. + * + * @param fieldname The field name to check. + * @return Whether or not this template should apply. + */ + public boolean matchFieldName(String fieldname) { + return this.fieldname.equals(fieldname); + } + + /** + * A builder class for creating {@code + * ExpectedFieldTypeAnnotation}s in a more convenient fashion. The + * constructor for {@code ExpectedFieldTypeAnnotation} takes a + * large number of parameters (by necessity). This class + * allows users to construct a {@code ExpectedFieldTypeAnnotation}s + * using only the ones they need. + */ + public static class Builder extends ExpectedTypeAnnotation.Builder { + protected final String fieldname; + + /** + * Create a {@code Builder} from the mandatory parameters. + * + * @param fieldname The expected field name. + * @param expectedName The expected annotation name. + * @param targetType The expected target type. + * @param visibility Whether this annotation should be runtime-visible. + * @param expectedCount The number of annotations that should be seen. + */ + public Builder(String fieldname, + String expectedName, + TypeAnnotation.TargetType targetType, + boolean visibility, + int expectedCount) { + super(expectedName, targetType, visibility, expectedCount); + this.fieldname = fieldname; + } + + /** + * Create an {@code ExpectedFieldTypeAnnotation} from all + * parameters that have been provided. The default values + * will be used for those that have not. + * + * @return The cretaed {@code ExpectedFieldTypeAnnotation}. + */ + public ExpectedFieldTypeAnnotation build() { + return new ExpectedFieldTypeAnnotation(fieldname, expectedName, + visibility, expectedCount, + targetType, bound_index, + parameter_index, type_index, + exception_index, typePath); + } + } + } + + private void matchClassAnnotation(ClassFile classfile, + ExpectedAnnotation expected) + throws ConstantPoolException { + for(Attribute attr : classfile.attributes) { + attr.accept(annoMatcher(classfile.constant_pool), expected); + } + } + + private void matchMethodAnnotation(ClassFile classfile, + ExpectedMethodAnnotation expected) + throws ConstantPoolException { + for(Method meth : classfile.methods) { + if (expected.matchMethodName(meth.getName(classfile.constant_pool))) { + for(Attribute attr : meth.attributes) { + attr.accept(annoMatcher(classfile.constant_pool), expected); + } + } + } + } + + private void matchParameterAnnotation(ClassFile classfile, + ExpectedParameterAnnotation expected) + throws ConstantPoolException { + for(Method meth : classfile.methods) { + if (expected.matchMethodName(meth.getName(classfile.constant_pool))) { + for(Attribute attr : meth.attributes) { + attr.accept(paramMatcher(classfile.constant_pool), expected); + } + } + } + } + + private void matchFieldAnnotation(ClassFile classfile, + ExpectedFieldAnnotation expected) + throws ConstantPoolException { + for(Field field : classfile.fields) { + if (expected.matchFieldName(field.getName(classfile.constant_pool))) { + for(Attribute attr : field.attributes) { + attr.accept(annoMatcher(classfile.constant_pool), expected); + } + } + } + } + + private void matchClassTypeAnnotation(ClassFile classfile, + ExpectedTypeAnnotation expected) + throws ConstantPoolException { + for(Attribute attr : classfile.attributes) { + attr.accept(typeAnnoMatcher, expected); + } + } + + private void matchMethodTypeAnnotation(ClassFile classfile, + ExpectedMethodTypeAnnotation expected) + throws ConstantPoolException { + for(Method meth : classfile.methods) { + if (expected.matchMethodName(meth.getName(classfile.constant_pool))) { + for(Attribute attr : meth.attributes) { + attr.accept(typeAnnoMatcher, expected); + } + } + } + } + + private void matchFieldTypeAnnotation(ClassFile classfile, + ExpectedFieldTypeAnnotation expected) + throws ConstantPoolException { + for(Field field : classfile.fields) { + if (expected.matchFieldName(field.getName(classfile.constant_pool))) { + for(Attribute attr : field.attributes) { + attr.accept(typeAnnoMatcher, expected); + } + } + } + } + + private void matchClassAnnotations(ClassFile classfile, + ExpectedAnnotation[] expected) + throws ConstantPoolException { + for(ExpectedAnnotation one : expected) { + matchClassAnnotation(classfile, one); + } + } + + private void matchMethodAnnotations(ClassFile classfile, + ExpectedMethodAnnotation[] expected) + throws ConstantPoolException { + for(ExpectedMethodAnnotation one : expected) { + matchMethodAnnotation(classfile, one); + } + } + + private void matchParameterAnnotations(ClassFile classfile, + ExpectedParameterAnnotation[] expected) + throws ConstantPoolException { + for(ExpectedParameterAnnotation one : expected) { + matchParameterAnnotation(classfile, one); + } + } + + private void matchFieldAnnotations(ClassFile classfile, + ExpectedFieldAnnotation[] expected) + throws ConstantPoolException { + for(ExpectedFieldAnnotation one : expected) { + matchFieldAnnotation(classfile, one); + } + } + + private void matchClassTypeAnnotations(ClassFile classfile, + ExpectedTypeAnnotation[] expected) + throws ConstantPoolException { + for(ExpectedTypeAnnotation one : expected) { + matchClassTypeAnnotation(classfile, one); + } + } + + private void matchMethodTypeAnnotations(ClassFile classfile, + ExpectedMethodTypeAnnotation[] expected) + throws ConstantPoolException { + for(ExpectedMethodTypeAnnotation one : expected) { + matchMethodTypeAnnotation(classfile, one); + } + } + + private void matchFieldTypeAnnotations(ClassFile classfile, + ExpectedFieldTypeAnnotation[] expected) + throws ConstantPoolException { + for(ExpectedFieldTypeAnnotation one : expected) { + matchFieldTypeAnnotation(classfile, one); + } + } + + /** + * Run a template on a single {@code ClassFile}. + * + * @param classfile The {@code ClassFile} on which to run tests. + * @param expected The expected annotation template. + */ + public void run(ClassFile classfile, + Expected... expected) + throws ConstantPoolException { + run(new ClassFile[] { classfile }, expected); + } + + /** + * Run a template on multiple {@code ClassFile}s. + * + * @param classfile The {@code ClassFile}s on which to run tests. + * @param expected The expected annotation template. + */ + public void run(ClassFile[] classfiles, + Expected... expected) + throws ConstantPoolException { + for(ClassFile classfile : classfiles) { + for(Expected one : expected) { + if (one.matchClassName(classfile.getName())) { + if (one.classAnnos != null) + matchClassAnnotations(classfile, one.classAnnos); + if (one.methodAnnos != null) + matchMethodAnnotations(classfile, one.methodAnnos); + if (one.methodParamAnnos != null) + matchParameterAnnotations(classfile, one.methodParamAnnos); + if (one.fieldAnnos != null) + matchFieldAnnotations(classfile, one.fieldAnnos); + if (one.classTypeAnnos != null) + matchClassTypeAnnotations(classfile, one.classTypeAnnos); + if (one.methodTypeAnnos != null) + matchMethodTypeAnnotations(classfile, one.methodTypeAnnos); + if (one.fieldTypeAnnos != null) + matchFieldTypeAnnotations(classfile, one.fieldTypeAnnos); + } + } + } + int count = 0; + for (Expected one : expected) { + count += one.check(); + } + + if (count != 0) { + throw new RuntimeException(count + " errors occurred in test"); + } + } + + /** + * Get a {@code ClassFile} from its file name. + * + * @param name The class' file name. + * @param host A class in the same package. + * @return The {@code ClassFile} + */ + public static ClassFile getClassFile(String name, + Class host) + throws IOException, ConstantPoolException { + final URL url = host.getResource(name); + final InputStream in = url.openStream(); + try { + return ClassFile.read(in); + } finally { + in.close(); + } + } + + private static final Attribute.Visitor typeAnnoMatcher = + new Attribute.Visitor() { + + @Override + public Void visitBootstrapMethods(BootstrapMethods_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitDefault(DefaultAttribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitAnnotationDefault(AnnotationDefault_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitCharacterRangeTable(CharacterRangeTable_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitCode(Code_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitCompilationID(CompilationID_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitConstantValue(ConstantValue_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitDeprecated(Deprecated_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitEnclosingMethod(EnclosingMethod_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitExceptions(Exceptions_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitInnerClasses(InnerClasses_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitLineNumberTable(LineNumberTable_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitLocalVariableTable(LocalVariableTable_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitMethodParameters(MethodParameters_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitSignature(Signature_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitSourceDebugExtension(SourceDebugExtension_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitSourceFile(SourceFile_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitSourceID(SourceID_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitStackMap(StackMap_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitStackMapTable(StackMapTable_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitSynthetic(Synthetic_attribute attr, + ExpectedTypeAnnotation expected) { + return null; + } + + @Override + public Void visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr, + ExpectedTypeAnnotation expected) { + if (expected.matchVisibility(true)) { + for(TypeAnnotation anno : attr.annotations) { + expected.matchAnnotation(anno); + } + } + + return null; + } + + @Override + public Void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr, + ExpectedTypeAnnotation expected) { + if (expected.matchVisibility(false)) { + for(TypeAnnotation anno : attr.annotations) { + expected.matchAnnotation(anno); + } + } + + return null; + } + }; + + private static Attribute.Visitor annoMatcher(ConstantPool cpool) { + return new Attribute.Visitor() { + + @Override + public Void visitBootstrapMethods(BootstrapMethods_attribute attr, + ExpectedAnnotation expected) { + return null; + } + + @Override + public Void visitDefault(DefaultAttribute attr, + ExpectedAnnotation expected) { + return null; + } + + @Override + public Void visitAnnotationDefault(AnnotationDefault_attribute attr, + ExpectedAnnotation expected) { + return null; + } + + @Override + public Void visitCharacterRangeTable(CharacterRangeTable_attribute attr, + ExpectedAnnotation expected) { + return null; + } + + @Override + public Void visitCode(Code_attribute attr, + ExpectedAnnotation expected) { + return null; + } + + @Override + public Void visitCompilationID(CompilationID_attribute attr, + ExpectedAnnotation expected) { + return null; + } + + @Override + public Void visitConstantValue(ConstantValue_attribute attr, + ExpectedAnnotation expected) { + return null; + } + + @Override + public Void visitDeprecated(Deprecated_attribute attr, + ExpectedAnnotation expected) { + return null; + } + + @Override + public Void visitEnclosingMethod(EnclosingMethod_attribute attr, + ExpectedAnnotation expected) { + return null; + } + + @Override + public Void visitExceptions(Exceptions_attribute attr, + ExpectedAnnotation expected) { + return null; + } + + @Override + public Void visitInnerClasses(InnerClasses_attribute attr, + ExpectedAnnotation expected) { + return null; + } + + @Override + public Void visitLineNumberTable(LineNumberTable_attribute attr, + ExpectedAnnotation expected) { + return null; + } + + @Override + public Void visitLocalVariableTable(LocalVariableTable_attribute attr, + ExpectedAnnotation expected) { + return null; + } + + @Override + public Void visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr, + ExpectedAnnotation expected) { + return null; + } + + @Override + public Void visitMethodParameters(MethodParameters_attribute attr, + ExpectedAnnotation expected) { + return null; + } + + @Override + public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, + ExpectedAnnotation expected) { + return null; + } + + @Override + public Void visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute attr, + ExpectedAnnotation expected) { + return null; + } + + @Override + public Void visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr, + ExpectedAnnotation expected) { + return null; + } + + @Override + public Void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr, + ExpectedAnnotation expected) { + return null; + } + + @Override + public Void visitSignature(Signature_attribute attr, + ExpectedAnnotation expected) { + return null; + } + + @Override + public Void visitSourceDebugExtension(SourceDebugExtension_attribute attr, + ExpectedAnnotation expected) { + return null; + } + + @Override + public Void visitSourceFile(SourceFile_attribute attr, + ExpectedAnnotation expected) { + return null; + } + + @Override + public Void visitSourceID(SourceID_attribute attr, + ExpectedAnnotation expected) { + return null; + } + + @Override + public Void visitStackMap(StackMap_attribute attr, + ExpectedAnnotation expected) { + return null; + } + + @Override + public Void visitStackMapTable(StackMapTable_attribute attr, + ExpectedAnnotation expected) { + return null; + } + + @Override + public Void visitSynthetic(Synthetic_attribute attr, + ExpectedAnnotation expected) { + return null; + } + + @Override + public Void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, + ExpectedAnnotation expected) { + if (expected.matchVisibility(true)) { + for(Annotation anno : attr.annotations) { + expected.matchAnnotation(cpool, anno); + } + } + + return null; + } + + @Override + public Void visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, + ExpectedAnnotation expected) { + if (expected.matchVisibility(false)) { + for(Annotation anno : attr.annotations) { + expected.matchAnnotation(cpool, anno); + } + } + + return null; + } + }; + } + + private static Attribute.Visitor paramMatcher(ConstantPool cpool) { + return new Attribute.Visitor() { + + @Override + public Void visitBootstrapMethods(BootstrapMethods_attribute attr, + ExpectedParameterAnnotation expected) { + return null; + } + + @Override + public Void visitDefault(DefaultAttribute attr, + ExpectedParameterAnnotation expected) { + return null; + } + + @Override + public Void visitAnnotationDefault(AnnotationDefault_attribute attr, + ExpectedParameterAnnotation expected) { + return null; + } + + @Override + public Void visitCharacterRangeTable(CharacterRangeTable_attribute attr, + ExpectedParameterAnnotation expected) { + return null; + } + + @Override + public Void visitCode(Code_attribute attr, + ExpectedParameterAnnotation expected) { + return null; + } + + @Override + public Void visitCompilationID(CompilationID_attribute attr, + ExpectedParameterAnnotation expected) { + return null; + } + + @Override + public Void visitConstantValue(ConstantValue_attribute attr, + ExpectedParameterAnnotation expected) { + return null; + } + + @Override + public Void visitDeprecated(Deprecated_attribute attr, + ExpectedParameterAnnotation expected) { + return null; + } + + @Override + public Void visitEnclosingMethod(EnclosingMethod_attribute attr, + ExpectedParameterAnnotation expected) { + return null; + } + + @Override + public Void visitExceptions(Exceptions_attribute attr, + ExpectedParameterAnnotation expected) { + return null; + } + + @Override + public Void visitInnerClasses(InnerClasses_attribute attr, + ExpectedParameterAnnotation expected) { + return null; + } + + @Override + public Void visitLineNumberTable(LineNumberTable_attribute attr, + ExpectedParameterAnnotation expected) { + return null; + } + + @Override + public Void visitLocalVariableTable(LocalVariableTable_attribute attr, + ExpectedParameterAnnotation expected) { + return null; + } + + @Override + public Void visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr, + ExpectedParameterAnnotation expected) { + return null; + } + + @Override + public Void visitMethodParameters(MethodParameters_attribute attr, + ExpectedParameterAnnotation expected) { + return null; + } + + @Override + public Void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, + ExpectedParameterAnnotation expected) { + return null; + } + + @Override + public Void visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, + ExpectedParameterAnnotation expected) { + return null; + } + + @Override + public Void visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr, + ExpectedParameterAnnotation expected) { + return null; + } + + @Override + public Void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr, + ExpectedParameterAnnotation expected) { + return null; + } + + @Override + public Void visitSignature(Signature_attribute attr, + ExpectedParameterAnnotation expected) { + return null; + } + + @Override + public Void visitSourceDebugExtension(SourceDebugExtension_attribute attr, + ExpectedParameterAnnotation expected) { + return null; + } + + @Override + public Void visitSourceFile(SourceFile_attribute attr, + ExpectedParameterAnnotation expected) { + return null; + } + + @Override + public Void visitSourceID(SourceID_attribute attr, + ExpectedParameterAnnotation expected) { + return null; + } + + @Override + public Void visitStackMap(StackMap_attribute attr, + ExpectedParameterAnnotation expected) { + return null; + } + + @Override + public Void visitStackMapTable(StackMapTable_attribute attr, + ExpectedParameterAnnotation expected) { + return null; + } + + @Override + public Void visitSynthetic(Synthetic_attribute attr, + ExpectedParameterAnnotation expected) { + return null; + } + + @Override + public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, + ExpectedParameterAnnotation expected) { + if (expected.matchVisibility(true)) { + if (expected.index < attr.parameter_annotations.length) { + for(Annotation anno : + attr.parameter_annotations[expected.index]) { + expected.matchAnnotation(cpool, anno); + } + } + } + + return null; + } + + @Override + public Void visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute attr, + ExpectedParameterAnnotation expected) { + if (expected.matchVisibility(false)) { + if (expected.index < attr.parameter_annotations.length) { + for(Annotation anno : + attr.parameter_annotations[expected.index]) { + expected.matchAnnotation(cpool, anno); + } + } + } + + return null; + } + }; + } +} diff -r d4c7822e9d64 -r 244e6dc77287 test/tools/javac/8062359/UnresolvableClassNPEInAttrTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/8062359/UnresolvableClassNPEInAttrTest.java Fri Dec 12 14:57:02 2014 -0800 @@ -0,0 +1,17 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8062359 + * @summary NullPointerException in Attr when type-annotating an anonymous + * inner class in an unresolvable class + * @compile/fail/ref=UnresolvableClassNPEInAttrTest.out -XDrawDiagnostics UnresolvableClassNPEInAttrTest.java + */ + +public class UnresolvableClassNPEInAttrTest { + public static void main(String[] args) { + new Undefined() { + void test() { + new Object() {}; + } + }; + } +} diff -r d4c7822e9d64 -r 244e6dc77287 test/tools/javac/8062359/UnresolvableClassNPEInAttrTest.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/8062359/UnresolvableClassNPEInAttrTest.out Fri Dec 12 14:57:02 2014 -0800 @@ -0,0 +1,2 @@ +UnresolvableClassNPEInAttrTest.java:11:13: compiler.err.cant.resolve.location: kindname.class, Undefined, , , (compiler.misc.location: kindname.class, UnresolvableClassNPEInAttrTest, null) +1 error diff -r d4c7822e9d64 -r 244e6dc77287 test/tools/javac/T8019486/WrongLNTForLambdaTest.java --- a/test/tools/javac/T8019486/WrongLNTForLambdaTest.java Mon Dec 01 11:39:34 2014 -0800 +++ b/test/tools/javac/T8019486/WrongLNTForLambdaTest.java Fri Dec 12 14:57:02 2014 -0800 @@ -138,7 +138,7 @@ checkClassFile(new File(Paths.get(System.getProperty("user.dir"), "Foo.class").toUri()), "$deserializeLambda$", deserializeExpectedLNT); checkClassFile(new File(Paths.get(System.getProperty("user.dir"), - "Foo.class").toUri()), "lambda$MR$variablesInLambdas$notify$8bc4f5bd$1", lambdaBridgeExpectedLNT); + "Foo.class").toUri()), "lambda$variablesInLambdas$3", lambdaBridgeExpectedLNT); checkClassFile(new File(Paths.get(System.getProperty("user.dir"), "Foo.class").toUri()), "assignLambda", assignmentExpectedLNT); checkClassFile(new File(Paths.get(System.getProperty("user.dir"), diff -r d4c7822e9d64 -r 244e6dc77287 test/tools/javac/T8059921/ForbidAccessToFieldUsingSuperTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/T8059921/ForbidAccessToFieldUsingSuperTest.java Fri Dec 12 14:57:02 2014 -0800 @@ -0,0 +1,31 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8059921 + * @summary Missing compile error in Java 8 mode for Interface.super.field access + * @compile/fail/ref=ForbidAccessToFieldUsingSuperTest.out -XDrawDiagnostics ForbidAccessToFieldUsingSuperTest.java + */ + +public class ForbidAccessToFieldUsingSuperTest { + class C { + int m() { return 0; } + } + + interface T { + int f = 0; + C c = null; + default int mm() { + return 0; + } + } + + interface T1 extends T {} + + class X implements T1 { + int i = T1.super.f; //fail + int j = T1.super.c.m(); //fail + + void foo(Runnable r) { + foo(T1.super::mm); //should'n fail + } + } +} diff -r d4c7822e9d64 -r 244e6dc77287 test/tools/javac/T8059921/ForbidAccessToFieldUsingSuperTest.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/T8059921/ForbidAccessToFieldUsingSuperTest.out Fri Dec 12 14:57:02 2014 -0800 @@ -0,0 +1,3 @@ +ForbidAccessToFieldUsingSuperTest.java:24:19: compiler.err.not.encl.class: ForbidAccessToFieldUsingSuperTest.T1 +ForbidAccessToFieldUsingSuperTest.java:25:19: compiler.err.not.encl.class: ForbidAccessToFieldUsingSuperTest.T1 +2 errors diff -r d4c7822e9d64 -r 244e6dc77287 test/tools/javac/annotations/SyntheticParameters.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/annotations/SyntheticParameters.java Fri Dec 12 14:57:02 2014 -0800 @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2014, 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 SyntheticParameters + * @bug 8065132 + * @summary Test generation of annotations on inner class parameters. + * @library /lib/annotations/ + * @run main SyntheticParameters + */ + +import annotations.classfile.ClassfileInspector; + +import java.io.*; +import java.lang.annotation.*; + +import com.sun.tools.classfile.*; + +public class SyntheticParameters extends ClassfileInspector { + + private static final String Inner_class = "SyntheticParameters$Inner.class"; + private static final String Foo_class = "SyntheticParameters$Foo.class"; + private static final Expected Inner_expected = + new Expected("SyntheticParameters$Inner", + null, + null, + new ExpectedParameterAnnotation[] { + (ExpectedParameterAnnotation) + // Assert there is no annotation on the + // this$0 parameter. + new ExpectedParameterAnnotation( + "", + 0, + "A", + true, + 0), + (ExpectedParameterAnnotation) + // Assert there is an annotation on the + // first parameter. + new ExpectedParameterAnnotation( + "", + 1, + "A", + true, + 1), + (ExpectedParameterAnnotation) + new ExpectedParameterAnnotation( + "foo", + 0, + "A", + true, + 1), + (ExpectedParameterAnnotation) + new ExpectedParameterAnnotation( + "foo", + 1, + "A", + true, + 0), + (ExpectedParameterAnnotation) + // Assert there is no annotation on the + // this$0 parameter. + new ExpectedParameterAnnotation( + "", + 0, + "B", + false, + 0), + (ExpectedParameterAnnotation) + // Assert there is an annotation on the + // first parameter. + new ExpectedParameterAnnotation( + "", + 1, + "B", + false, + 1), + (ExpectedParameterAnnotation) + new ExpectedParameterAnnotation( + "foo", + 0, + "B", + false, + 1), + (ExpectedParameterAnnotation) + new ExpectedParameterAnnotation( + "foo", + 1, + "B", + false, + 0) + }, + null); + private static final Expected Foo_expected = + new Expected("SyntheticParameters$Foo", + null, + null, + new ExpectedParameterAnnotation[] { + (ExpectedParameterAnnotation) + // Assert there is no annotation on the + // $enum$name parameter. + new ExpectedParameterAnnotation( + "", + 0, + "A", + true, + 0), + (ExpectedParameterAnnotation) + // Assert there is no annotation on the + // $enum$ordinal parameter. + new ExpectedParameterAnnotation( + "", + 1, + "A", + true, + 0), + (ExpectedParameterAnnotation) + // Assert there is an annotation on the + // first parameter. + new ExpectedParameterAnnotation( + "", + 2, + "A", + true, + 1), + (ExpectedParameterAnnotation) + // Assert there is no annotation on the + // $enum$name parameter. + new ExpectedParameterAnnotation( + "", + 0, + "B", + false, + 0), + (ExpectedParameterAnnotation) + // Assert there is no annotation on the + // $enum$ordinal parameter. + new ExpectedParameterAnnotation( + "", + 1, + "B", + false, + 0), + (ExpectedParameterAnnotation) + // Assert there is an annotation on the + // first parameter. + new ExpectedParameterAnnotation( + "", + 2, + "B", + false, + 1) + }, + null); + + public static void main(String... args) throws Exception { + new SyntheticParameters().run( + new ClassFile[] { getClassFile(Inner_class, Inner.class), + getClassFile(Foo_class, Foo.class) }, + new Expected[] { Inner_expected, Foo_expected }); + } + + public class Inner { + public Inner(@A @B int a) {} + public void foo(@A @B int a, int b) {} + } + + public static enum Foo { + ONE(null); + Foo(@A @B Object a) {} + } +} + +@Retention(RetentionPolicy.RUNTIME) +@interface A {} + +@Retention(RetentionPolicy.CLASS) +@interface B {} diff -r d4c7822e9d64 -r 244e6dc77287 test/tools/javac/annotations/typeAnnotations/classfile/SyntheticParameters.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/annotations/typeAnnotations/classfile/SyntheticParameters.java Fri Dec 12 14:57:02 2014 -0800 @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2014, 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 SyntheticParameters + * @summary Test generation of annotations on inner class parameters. + * @library /lib/annotations/ + * @run main SyntheticParameters + */ + +import annotations.classfile.ClassfileInspector; + +import java.io.*; +import java.lang.annotation.*; + +import com.sun.tools.classfile.*; + +public class SyntheticParameters extends ClassfileInspector { + + private static final String Inner_class = "SyntheticParameters$Inner.class"; + private static final String Foo_class = "SyntheticParameters$Foo.class"; + private static final Expected Inner_expected = + new Expected("SyntheticParameters$Inner", + null, + new ExpectedMethodTypeAnnotation[] { + (ExpectedMethodTypeAnnotation) + // Assert there is no annotation on the + // this$0 parameter. + new ExpectedMethodTypeAnnotation.Builder( + "", + "A", + TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER, + false, + 0).setParameterIndex(0).build(), + (ExpectedMethodTypeAnnotation) + // Assert there is an annotation on the + // first parameter. + new ExpectedMethodTypeAnnotation.Builder( + "", + "A", + TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER, + false, + 1).setParameterIndex(1).build(), + (ExpectedMethodTypeAnnotation) + new ExpectedMethodTypeAnnotation.Builder( + "foo", + "A", + TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER, + false, + 1).setParameterIndex(0).build(), + (ExpectedMethodTypeAnnotation) + new ExpectedMethodTypeAnnotation.Builder( + "foo", + "A", + TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER, + false, + 0).setParameterIndex(1).build() + }, + null); + private static final Expected Foo_expected = + new Expected("SyntheticParameters$Foo", + null, + new ExpectedMethodTypeAnnotation[] { + (ExpectedMethodTypeAnnotation) + // Assert there is no annotation on the + // $enum$name parameter. + new ExpectedMethodTypeAnnotation.Builder( + "", + "A", + TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER, + false, + 0).setParameterIndex(0).build(), + (ExpectedMethodTypeAnnotation) + // Assert there is no annotation on the + // $enum$ordinal parameter. + new ExpectedMethodTypeAnnotation.Builder( + "", + "A", + TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER, + false, + 0).setParameterIndex(1).build(), + (ExpectedMethodTypeAnnotation) + // Assert there is an annotation on the + // first parameter. + new ExpectedMethodTypeAnnotation.Builder( + "", + "A", + TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER, + false, + 1).setParameterIndex(2).build() + }, + null); + + public static void main(String... args) throws Exception { + new SyntheticParameters().run( + new ClassFile[] { getClassFile(Inner_class, Inner.class), + getClassFile(Foo_class, Foo.class) }, + new Expected[] { Inner_expected, Foo_expected }); + } + + public class Inner { + public Inner(@A int a) {} + public void foo(@A int a, int b) {} + } + + public static enum Foo { + ONE(null); + Foo(@A Object a) {} + } +} + +@Target({ElementType.TYPE_USE}) +@interface A {} diff -r d4c7822e9d64 -r 244e6dc77287 test/tools/javac/annotations/typeAnnotations/referenceinfos/Constructors.java --- a/test/tools/javac/annotations/typeAnnotations/referenceinfos/Constructors.java Mon Dec 01 11:39:34 2014 -0800 +++ b/test/tools/javac/annotations/typeAnnotations/referenceinfos/Constructors.java Fri Dec 12 14:57:02 2014 -0800 @@ -46,7 +46,7 @@ @TADescriptions({ @TADescription(annotation = "TA", type = METHOD_RETURN, genericLocation = {1, 0}), @TADescription(annotation = "TB", type = METHOD_RETURN, genericLocation = {1, 0}), - @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, paramIndex = 0) + @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, paramIndex = 1) }) @TestClass("Test$Inner") public String innerClass() { @@ -61,7 +61,7 @@ @TADescription(annotation = "TB", type = METHOD_RETURN, genericLocation = {1, 0}), @TADescription(annotation = "TC", type = METHOD_RECEIVER), @TADescription(annotation = "TD", type = METHOD_RETURN, genericLocation = {1, 0}), - @TADescription(annotation = "TE", type = METHOD_FORMAL_PARAMETER, paramIndex = 0) + @TADescription(annotation = "TE", type = METHOD_FORMAL_PARAMETER, paramIndex = 1) }) @TestClass("Test$Inner") public String innerClass2() { @@ -77,7 +77,7 @@ @TADescription(annotation = "TC", type = METHOD_RETURN, genericLocation = {1, 0, 1, 0}), @TADescription(annotation = "TD", type = METHOD_RECEIVER, genericLocation = {1, 0}), @TADescription(annotation = "TE", type = METHOD_RETURN, genericLocation = {1, 0, 1, 0}), - @TADescription(annotation = "TF", type = METHOD_FORMAL_PARAMETER, paramIndex = 0) + @TADescription(annotation = "TF", type = METHOD_FORMAL_PARAMETER, paramIndex = 1) }) @TestClass("Outer$Middle$Inner") public String innerClass3() { diff -r d4c7822e9d64 -r 244e6dc77287 test/tools/javac/flow/T8062747.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/flow/T8062747.java Fri Dec 12 14:57:02 2014 -0800 @@ -0,0 +1,24 @@ +/** + * @test + * @bug 8062747 + * @summary Avoiding an error for lambdas with thrown types inference inside an anonymous class. + * @compile T8062747.java + */ +public class T8062747 { + + public interface Throwing { + void canThrow() throws Y; + } + + public static void wrap(Throwing action) { + } + + public static void invoke(String a) { + Runnable r = new Runnable() { + @Override + public void run() { + wrap(() -> System.out.println(a)); + } + }; + } +} diff -r d4c7822e9d64 -r 244e6dc77287 test/tools/javac/lambda/T8057794.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/lambda/T8057794.java Fri Dec 12 14:57:02 2014 -0800 @@ -0,0 +1,12 @@ +/** + * @test /nodynamiccopyright/ + * @bug 8057794 + * @summary The tree for TypeVar.class does not have a type set, which leads to an NPE when + * checking if deferred attribution is needed + * @compile/fail/ref=T8057794.out -XDrawDiagnostics T8057794.java + */ +class T8057794 { + void t() { + System.out.println(T.class.getSimpleName()); + } +} diff -r d4c7822e9d64 -r 244e6dc77287 test/tools/javac/lambda/T8057794.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/lambda/T8057794.out Fri Dec 12 14:57:02 2014 -0800 @@ -0,0 +1,2 @@ +T8057794.java:10:29: compiler.err.type.var.cant.be.deref +1 error diff -r d4c7822e9d64 -r 244e6dc77287 test/tools/javac/lambda/methodReference/MethodRef8.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/lambda/methodReference/MethodRef8.java Fri Dec 12 14:57:02 2014 -0800 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2014, 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 8063052 + * @summary Inference chokes on wildcard derived from method reference + * @compile MethodRef8.java + */ + +public class MethodRef8 { + void test(Box> b) { + Number n1 = b.map(Box::get).get(); + Number n2 = b.map(Box::get).get(); + } + + interface Func { T apply(S arg); } + + interface Box { + T get(); + Box map(Func f); + } +} diff -r d4c7822e9d64 -r 244e6dc77287 test/tools/javac/lambda/methodReference/MethodRefNewInnerBootstrap.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/lambda/methodReference/MethodRefNewInnerBootstrap.java Fri Dec 12 14:57:02 2014 -0800 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2014, 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 8044748 + * @summary JVM cannot access constructor though ::new reference although can call it directly + */ + +public class MethodRefNewInnerBootstrap { + + interface Constructor { + public MyTest execute(int i); + } + + public class MyTest { + public MyTest(int i) { System.out.println("Constructor executed " + i); } + } + + public Constructor getConstructor() { + return MyTest::new; + } + + public static void main(String argv[]) { + new MethodRefNewInnerBootstrap().call(); + } + + public void call() { + MyTest mt = new MyTest(0); + + Constructor c1 = MyTest::new; + c1.execute(1); + + Constructor c2 = getConstructor(); + c2.execute(2); + + Constructor c3 = new Constructor() { + public MyTest execute(int i) { + return new MyTest(3); + } + }; + c3.execute(3); + + Constructor c4 = new Constructor() { + public MyTest execute(int i) { + Constructor c = MyTest::new; + return c.execute(i); + } + }; + c4.execute(4); + } +} diff -r d4c7822e9d64 -r 244e6dc77287 test/tools/javac/lambda/methodReference/MethodRefNewInnerInLambdaNPE1.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/lambda/methodReference/MethodRefNewInnerInLambdaNPE1.java Fri Dec 12 14:57:02 2014 -0800 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014, 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 8037404 + * @summary javac NPE or VerifyError for code with constructor reference of inner class + */ + +import java.util.function.Supplier; +import java.util.stream.Stream; + +public class MethodRefNewInnerInLambdaNPE1 { + public static void main(String[] args) { + if (new MethodRefNewInnerInLambdaNPE1().getList().get().getClass() != TT.class) + throw new AssertionError("sanity failed"); + } + + Supplier getList() { + return () -> Stream.of(1).map(TT::new).findFirst().get(); + } + + class TT { + public TT(int i) { + + } + } +} diff -r d4c7822e9d64 -r 244e6dc77287 test/tools/javac/lambda/methodReference/MethodRefNewInnerInLambdaNPE2.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/lambda/methodReference/MethodRefNewInnerInLambdaNPE2.java Fri Dec 12 14:57:02 2014 -0800 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2014, 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 8044737 + * @summary Lambda: NPE while obtaining method reference through lambda expression + * @compile MethodRefNewInnerInLambdaNPE2.java + */ + +public class MethodRefNewInnerInLambdaNPE2 { + + interface Constructor { + MyTest execute(); + } + + class MyTest { + MyTest() { System.out.println("Constructor executed"); } + } + + public Constructor getConstructor() { + return getConstructor(() -> { return MyTest::new; }); + } + + public static void main(String argv[]) { + MethodRefNewInnerInLambdaNPE2 t = new MethodRefNewInnerInLambdaNPE2(); + MyTest mytest = t.getConstructor().execute(); + } + + Constructor getConstructor(Wrapper arg) { + return arg.unwrap(); + } + + interface Wrapper { + Constructor unwrap(); + } +} diff -r d4c7822e9d64 -r 244e6dc77287 test/tools/javac/lambda/methodReference/MethodRefNewInnerInLambdaVerify1.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/lambda/methodReference/MethodRefNewInnerInLambdaVerify1.java Fri Dec 12 14:57:02 2014 -0800 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014, 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 8037404 + * @summary javac NPE or VerifyError for code with constructor reference of inner class + */ + +import java.util.function.Function; +import java.util.stream.Stream; + +public class MethodRefNewInnerInLambdaVerify1 { + public static void main(String[] args) { + if (new MethodRefNewInnerInLambdaVerify1().map().apply(1).getClass() != TT.class) + throw new AssertionError("sanity failed"); + } + + Function map() { + return (i) -> Stream.of(i).map(TT::new).findFirst().get(); + } + + class TT { + public TT(int i) { + + } + } +} diff -r d4c7822e9d64 -r 244e6dc77287 test/tools/javac/lambda/methodReference/MethodRefNewInnerInLambdaVerify2.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/lambda/methodReference/MethodRefNewInnerInLambdaVerify2.java Fri Dec 12 14:57:02 2014 -0800 @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2014, 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 8038776 + * @summary VerifyError when running successfully compiled java class + */ + +import java.util.function.Function; + +/** + * Derived from code by: + * @author Yawkat + */ +public class MethodRefNewInnerInLambdaVerify2 { + public static void main(String[] args) { new MethodRefNewInnerInLambdaVerify2().runTest(); } + + private void runTest() { + Worker worker = new Worker(); + run(() -> worker.check(field -> new SomeClass(field))); + run(() -> worker.check(SomeClass::new)); + } + + private void run(Runnable runnable) { + runnable.run(); + } + + private class SomeClass { + final Object field; + + SomeClass(Object field) { + this.field = field; + } + } + + private static class Worker { + void check(Function i) { + if (!i.apply("frank").field.equals("frank")) throw new AssertionError("sanity failed"); + } + } +} diff -r d4c7822e9d64 -r 244e6dc77287 test/tools/javac/lambda/methodReference/MethodRefNewInnerInLambdaVerify2simple.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/lambda/methodReference/MethodRefNewInnerInLambdaVerify2simple.java Fri Dec 12 14:57:02 2014 -0800 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2014, 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 8038776 + * @summary VerifyError when running successfully compiled java class + */ + +import java.util.function.Function; + +/** + * Derived from code by: + * @author Yawkat + */ +public class MethodRefNewInnerInLambdaVerify2simple { + public static void main(String[] args) { new MethodRefNewInnerInLambdaVerify2simple().runTest(); } + + private void runTest() { + Runnable r = (() -> { Sup w = SomeClass::new; } ); + } + + private class SomeClass { + SomeClass() { } + } +} + +interface Sup { + Object get(); +} diff -r d4c7822e9d64 -r 244e6dc77287 test/tools/javac/lambda/methodReference/MethodRefQualifier1.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/lambda/methodReference/MethodRefQualifier1.java Fri Dec 12 14:57:02 2014 -0800 @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2014, 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 8048121 + * @summary javac complex method references: revamp and simplify + */ + +public class MethodRefQualifier1 { + + interface SAM { + void m(); + } + + static int count = 0; + + static void assertTrue(boolean cond, String msg) { + if (!cond) + throw new AssertionError(msg); + } + + MethodRefQualifier1 check() { + count++; + return this; + } + + void ido(Object... args) { } + + public static void main(String[] args) { + new MethodRefQualifier1().test(); + } + + void test() { + count = 0; + SAM s = check()::ido; + assertTrue(count == 1, "creation: unexpected: " + count); + count = 0; + s.m(); + assertTrue(count == 0, "evaluation: unexpected: " + count); + } +} diff -r d4c7822e9d64 -r 244e6dc77287 test/tools/javac/lambda/methodReference/MethodRefSingleRefEvalBridge.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/lambda/methodReference/MethodRefSingleRefEvalBridge.java Fri Dec 12 14:57:02 2014 -0800 @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2014, 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 8048121 + * @summary javac complex method references: revamp and simplify + * + * Make sure that the method reference receiver is evaluated exactly once + * even in this bridging case. + */ + + public class MethodRefSingleRefEvalBridge { + + interface SAM { + int m(); + } + + class ZZ { + // private to force bridging + private int four() { return 4; } + } + + static int count = 0; + ZZ azz = new ZZ(); + + static void assertEqual(int expected, int got) { + if (got != expected) + throw new AssertionError("Expected " + expected + " got " + got); + } + + public static void main(String[] args) { + new MethodRefSingleRefEvalBridge().test(); + } + + ZZ check() { + count++; + return azz; + } + + void test() { + count = 0; + SAM s = check()::four; + assertEqual(1, count); + + count = 0; + assertEqual(4, s.m()); + assertEqual(0, count); + } +} diff -r d4c7822e9d64 -r 244e6dc77287 test/tools/javac/lambda/methodReference/MethodRefToInner.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/lambda/methodReference/MethodRefToInner.java Fri Dec 12 14:57:02 2014 -0800 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2014, 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 8047341 + * @summary lambda reference to inner class in base class causes LambdaConversionException + */ + +import java.util.List; +import java.util.ArrayList; + +class MethodRefToInnerBase { + class TestString { + String str; + TestString(String strin) { + str = strin; + } + } +} +public class MethodRefToInner extends MethodRefToInnerBase { + public static void main(String[] args) { + new MethodRefToInner().run(); + } + MethodRefToInner() { + super(); + } + void run() { + List list = new ArrayList<>(); + list.stream().forEach(TestString::new); + } +} diff -r d4c7822e9d64 -r 244e6dc77287 test/tools/javac/lambda/methodReference/MethodReferenceComplexNullCheckTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/lambda/methodReference/MethodReferenceComplexNullCheckTest.java Fri Dec 12 14:57:02 2014 -0800 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2014, 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. + */ + +/** + * @test + * @bug 8048121 + * @summary javac complex method references: revamp and simplify + * + * Make sure NPE check is done even in the convert to Lambda case + */ + +public class MethodReferenceComplexNullCheckTest { + public static void main(String[] args) { + F fr = null; + boolean npeFired = false; + try { + IForm frf = fr::doit; + } catch (NullPointerException npe) { + npeFired = true; + } finally { + if (!npeFired) throw new AssertionError( "NPE should have been thrown"); + } + } + + interface IForm { + void xyz(Object... args); + } + + class F { + private void doit(Object... args) { } + } +} diff -r d4c7822e9d64 -r 244e6dc77287 test/tools/javac/lambda/methodReferenceExecution/MethodReferenceIntersection1.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/lambda/methodReferenceExecution/MethodReferenceIntersection1.java Fri Dec 12 14:57:02 2014 -0800 @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2014, 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. + */ + +/** + * @test + * @bug 8058112 + * @summary Invalid BootstrapMethod for constructor/method reference + */ + +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; + +import static java.util.stream.Collectors.toList; + +public class MethodReferenceIntersection1 { + + public static void main(String[] args) { + MethodReferenceIntersection1 main = new MethodReferenceIntersection1(); + List list = main.toInfoListError(Arrays.asList(new Base_MRI1())); + System.out.printf("result %d\n", list.size()); + } + + public List toInfoListError(List list) { + Comparator byNameComparator = + (B_MRI1 b1, B_MRI1 b2) -> b1.getB().compareToIgnoreCase(b2.getB()); + return list.stream().sorted(byNameComparator).map(Info_MRI1::new).collect(toList()); + } + + public List toInfoListWorks(List list) { + Comparator byNameComparator = + (B_MRI1 b1, B_MRI1 b2) -> b1.getB().compareToIgnoreCase(b2.getB()); + return list.stream().sorted(byNameComparator).map(s -> new Info_MRI1(s)).collect(toList()); + } +} + +interface B_MRI1 { + public String getB(); +} + +interface A_MRI1 { + public long getA(); +} + +class Info_MRI1 { + private final long a; + private final String b; + + Info_MRI1(H h) { + a = h.getA(); + b = h.getB(); + } +} + +class Base_MRI1 implements A_MRI1, B_MRI1 { + + @Override + public long getA() { + return 7L; + } + + @Override + public String getB() { + return "hello"; + } +} diff -r d4c7822e9d64 -r 244e6dc77287 test/tools/javac/lambda/methodReferenceExecution/MethodReferenceIntersection2.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/lambda/methodReferenceExecution/MethodReferenceIntersection2.java Fri Dec 12 14:57:02 2014 -0800 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2014, 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. + */ + +/** + * @test + * @bug 8058112 + * @summary Invalid BootstrapMethod for constructor/method reference + */ + +import java.util.function.Function; + +public class MethodReferenceIntersection2 { + + interface B { } + + interface A { } + + static class C implements A, B { } + + static class Info { + Info(H h) { } + + static Info info(H h) { + return new Info(h); + } + } + + public static void main(String[] args) { + test(); + } + + // Note the switch in order compared to that on Info + static void test() { + Function f1L = _h -> new Info(_h); + Function f1 = Info::new; + Function f2L = _h -> Info.info(_h); + Function f2 = Info::info; + H c = (H) new C(); + if(f1.apply(c) instanceof Info && + f2.apply(c) instanceof Info) { + System.out.println("Passes."); + } else { + throw new AssertionError(); + } + } +} diff -r d4c7822e9d64 -r 244e6dc77287 test/tools/javac/lambda/methodReferenceExecution/MethodReferenceIntersection3.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/lambda/methodReferenceExecution/MethodReferenceIntersection3.java Fri Dec 12 14:57:02 2014 -0800 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2014, 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. + */ + +/** + * @test + * @bug 8058112 + * @summary Invalid BootstrapMethod for constructor/method reference + */ + +/** + * @author Remi Forax + */ + +public class MethodReferenceIntersection3 { + interface A {} + + interface Foo { + void foo(T t); + } + + static void bar(T t) { + } + + public static void main(String[] args) { + Foo foo = MethodReferenceIntersection3::bar; + foo.foo(new A(){}); + } +}