31 import java.util.Locale; |
31 import java.util.Locale; |
32 import java.util.Map; |
32 import java.util.Map; |
33 import java.util.Set; |
33 import java.util.Set; |
34 import java.util.WeakHashMap; |
34 import java.util.WeakHashMap; |
35 |
35 |
|
36 import javax.tools.JavaFileObject; |
|
37 |
36 import com.sun.tools.javac.code.Attribute.RetentionPolicy; |
38 import com.sun.tools.javac.code.Attribute.RetentionPolicy; |
37 import com.sun.tools.javac.code.Lint.LintCategory; |
39 import com.sun.tools.javac.code.Lint.LintCategory; |
38 import com.sun.tools.javac.code.Type.UndetVar.InferenceBound; |
40 import com.sun.tools.javac.code.Type.UndetVar.InferenceBound; |
|
41 import com.sun.tools.javac.comp.AttrContext; |
39 import com.sun.tools.javac.comp.Check; |
42 import com.sun.tools.javac.comp.Check; |
|
43 import com.sun.tools.javac.comp.Enter; |
|
44 import com.sun.tools.javac.comp.Env; |
40 import com.sun.tools.javac.jvm.ClassReader; |
45 import com.sun.tools.javac.jvm.ClassReader; |
41 import com.sun.tools.javac.util.*; |
46 import com.sun.tools.javac.util.*; |
42 import static com.sun.tools.javac.code.BoundKind.*; |
47 import static com.sun.tools.javac.code.BoundKind.*; |
43 import static com.sun.tools.javac.code.Flags.*; |
48 import static com.sun.tools.javac.code.Flags.*; |
44 import static com.sun.tools.javac.code.Scope.*; |
49 import static com.sun.tools.javac.code.Scope.*; |
81 final boolean allowCovariantReturns; |
86 final boolean allowCovariantReturns; |
82 final boolean allowObjectToPrimitiveCast; |
87 final boolean allowObjectToPrimitiveCast; |
83 final boolean allowDefaultMethods; |
88 final boolean allowDefaultMethods; |
84 final ClassReader reader; |
89 final ClassReader reader; |
85 final Check chk; |
90 final Check chk; |
|
91 final Enter enter; |
86 JCDiagnostic.Factory diags; |
92 JCDiagnostic.Factory diags; |
87 List<Warner> warnStack = List.nil(); |
93 List<Warner> warnStack = List.nil(); |
88 final Name capturedName; |
94 final Name capturedName; |
89 private final FunctionDescriptorLookupError functionDescriptorLookupError; |
95 private final FunctionDescriptorLookupError functionDescriptorLookupError; |
90 |
96 |
107 allowCovariantReturns = source.allowCovariantReturns(); |
113 allowCovariantReturns = source.allowCovariantReturns(); |
108 allowObjectToPrimitiveCast = source.allowObjectToPrimitiveCast(); |
114 allowObjectToPrimitiveCast = source.allowObjectToPrimitiveCast(); |
109 allowDefaultMethods = source.allowDefaultMethods(); |
115 allowDefaultMethods = source.allowDefaultMethods(); |
110 reader = ClassReader.instance(context); |
116 reader = ClassReader.instance(context); |
111 chk = Check.instance(context); |
117 chk = Check.instance(context); |
|
118 enter = Enter.instance(context); |
112 capturedName = names.fromString("<captured wildcard>"); |
119 capturedName = names.fromString("<captured wildcard>"); |
113 messages = JavacMessages.instance(context); |
120 messages = JavacMessages.instance(context); |
114 diags = JCDiagnostic.Factory.instance(context); |
121 diags = JCDiagnostic.Factory.instance(context); |
115 functionDescriptorLookupError = new FunctionDescriptorLookupError(); |
122 functionDescriptorLookupError = new FunctionDescriptorLookupError(); |
116 noWarnings = new Warner(null); |
123 noWarnings = new Warner(null); |
603 return subst(formalInterface, formalInterface.getTypeArguments(), typeargs.toList()); |
610 return subst(formalInterface, formalInterface.getTypeArguments(), typeargs.toList()); |
604 } else { |
611 } else { |
605 return site; |
612 return site; |
606 } |
613 } |
607 } |
614 } |
|
615 |
|
616 /** |
|
617 * Create a symbol for a class that implements a given functional interface |
|
618 * and overrides its functional descriptor. This routine is used for two |
|
619 * main purposes: (i) checking well-formedness of a functional interface; |
|
620 * (ii) perform functional interface bridge calculation. |
|
621 */ |
|
622 public ClassSymbol makeFunctionalInterfaceClass(Env<AttrContext> env, Name name, List<Type> targets, long cflags) { |
|
623 Assert.check(targets.nonEmpty() && isFunctionalInterface(targets.head)); |
|
624 Symbol descSym = findDescriptorSymbol(targets.head.tsym); |
|
625 Type descType = findDescriptorType(targets.head); |
|
626 ClassSymbol csym = new ClassSymbol(cflags, name, env.enclClass.sym.outermostClass()); |
|
627 csym.completer = null; |
|
628 csym.members_field = new Scope(csym); |
|
629 MethodSymbol instDescSym = new MethodSymbol(descSym.flags(), descSym.name, descType, csym); |
|
630 csym.members_field.enter(instDescSym); |
|
631 Type.ClassType ctype = new Type.ClassType(Type.noType, List.<Type>nil(), csym); |
|
632 ctype.supertype_field = syms.objectType; |
|
633 ctype.interfaces_field = targets; |
|
634 csym.type = ctype; |
|
635 csym.sourcefile = ((ClassSymbol)csym.owner).sourcefile; |
|
636 return csym; |
|
637 } |
|
638 |
|
639 /** |
|
640 * Find the minimal set of methods that are overridden by the functional |
|
641 * descriptor in 'origin'. All returned methods are assumed to have different |
|
642 * erased signatures. |
|
643 */ |
|
644 public List<Symbol> functionalInterfaceBridges(TypeSymbol origin) { |
|
645 Assert.check(isFunctionalInterface(origin)); |
|
646 Symbol descSym = findDescriptorSymbol(origin); |
|
647 CompoundScope members = membersClosure(origin.type, false); |
|
648 ListBuffer<Symbol> overridden = ListBuffer.lb(); |
|
649 outer: for (Symbol m2 : members.getElementsByName(descSym.name, bridgeFilter)) { |
|
650 if (m2 == descSym) continue; |
|
651 else if (descSym.overrides(m2, origin, Types.this, false)) { |
|
652 for (Symbol m3 : overridden) { |
|
653 if (isSameType(m3.erasure(Types.this), m2.erasure(Types.this)) || |
|
654 (m3.overrides(m2, origin, Types.this, false) && |
|
655 (pendingBridges((ClassSymbol)origin, m3.enclClass()) || |
|
656 (((MethodSymbol)m2).binaryImplementation((ClassSymbol)m3.owner, Types.this) != null)))) { |
|
657 continue outer; |
|
658 } |
|
659 } |
|
660 overridden.add(m2); |
|
661 } |
|
662 } |
|
663 return overridden.toList(); |
|
664 } |
|
665 //where |
|
666 private Filter<Symbol> bridgeFilter = new Filter<Symbol>() { |
|
667 public boolean accepts(Symbol t) { |
|
668 return t.kind == Kinds.MTH && |
|
669 t.name != names.init && |
|
670 t.name != names.clinit && |
|
671 (t.flags() & SYNTHETIC) == 0; |
|
672 } |
|
673 }; |
|
674 private boolean pendingBridges(ClassSymbol origin, TypeSymbol s) { |
|
675 //a symbol will be completed from a classfile if (a) symbol has |
|
676 //an associated file object with CLASS kind and (b) the symbol has |
|
677 //not been entered |
|
678 if (origin.classfile != null && |
|
679 origin.classfile.getKind() == JavaFileObject.Kind.CLASS && |
|
680 enter.getEnv(origin) == null) { |
|
681 return false; |
|
682 } |
|
683 if (origin == s) { |
|
684 return true; |
|
685 } |
|
686 for (Type t : interfaces(origin.type)) { |
|
687 if (pendingBridges((ClassSymbol)t.tsym, s)) { |
|
688 return true; |
|
689 } |
|
690 } |
|
691 return false; |
|
692 } |
608 // </editor-fold> |
693 // </editor-fold> |
609 |
694 |
610 /** |
695 /** |
611 * Scope filter used to skip methods that should be ignored (such as methods |
696 * Scope filter used to skip methods that should be ignored (such as methods |
612 * overridden by j.l.Object) during function interface conversion interface check |
697 * overridden by j.l.Object) during function interface conversion interface check |