119 memberEnter = MemberEnter.instance(context); |
120 memberEnter = MemberEnter.instance(context); |
120 typeEnter = TypeEnter.instance(context); |
121 typeEnter = TypeEnter.instance(context); |
121 make = TreeMaker.instance(context); |
122 make = TreeMaker.instance(context); |
122 enter = Enter.instance(context); |
123 enter = Enter.instance(context); |
123 infer = Infer.instance(context); |
124 infer = Infer.instance(context); |
|
125 analyzer = Analyzer.instance(context); |
124 deferredAttr = DeferredAttr.instance(context); |
126 deferredAttr = DeferredAttr.instance(context); |
125 cfolder = ConstFold.instance(context); |
127 cfolder = ConstFold.instance(context); |
126 target = Target.instance(context); |
128 target = Target.instance(context); |
127 types = Types.instance(context); |
129 types = Types.instance(context); |
128 diags = JCDiagnostic.Factory.instance(context); |
130 diags = JCDiagnostic.Factory.instance(context); |
141 allowLambda = source.allowLambda(); |
143 allowLambda = source.allowLambda(); |
142 allowDefaultMethods = source.allowDefaultMethods(); |
144 allowDefaultMethods = source.allowDefaultMethods(); |
143 allowStaticInterfaceMethods = source.allowStaticInterfaceMethods(); |
145 allowStaticInterfaceMethods = source.allowStaticInterfaceMethods(); |
144 sourceName = source.name; |
146 sourceName = source.name; |
145 relax = (options.isSet("-retrofit") || |
147 relax = (options.isSet("-retrofit") || |
146 options.isSet("-relax")); |
148 options.isSet("-relax")); |
147 findDiamonds = options.get("findDiamond") != null && |
|
148 source.allowDiamond(); |
|
149 useBeforeDeclarationWarning = options.isSet("useBeforeDeclarationWarning"); |
149 useBeforeDeclarationWarning = options.isSet("useBeforeDeclarationWarning"); |
150 identifyLambdaCandidate = options.getBoolean("identifyLambdaCandidate", false); |
|
151 |
150 |
152 statInfo = new ResultInfo(KindSelector.NIL, Type.noType); |
151 statInfo = new ResultInfo(KindSelector.NIL, Type.noType); |
153 varAssignmentInfo = new ResultInfo(KindSelector.ASG, Type.noType); |
152 varAssignmentInfo = new ResultInfo(KindSelector.ASG, Type.noType); |
154 unknownExprInfo = new ResultInfo(KindSelector.VAL, Type.noType); |
153 unknownExprInfo = new ResultInfo(KindSelector.VAL, Type.noType); |
155 unknownAnyPolyInfo = new ResultInfo(KindSelector.VAL, Infer.anyPoly); |
154 unknownAnyPolyInfo = new ResultInfo(KindSelector.VAL, Infer.anyPoly); |
180 |
179 |
181 /** Switch: static interface methods enabled? |
180 /** Switch: static interface methods enabled? |
182 */ |
181 */ |
183 boolean allowStaticInterfaceMethods; |
182 boolean allowStaticInterfaceMethods; |
184 |
183 |
185 /** Switch: generates a warning if diamond can be safely applied |
|
186 * to a given new expression |
|
187 */ |
|
188 boolean findDiamonds; |
|
189 |
|
190 /** |
|
191 * Internally enables/disables diamond finder feature |
|
192 */ |
|
193 static final boolean allowDiamondFinder = true; |
|
194 |
|
195 /** |
184 /** |
196 * Switch: warn about use of variable before declaration? |
185 * Switch: warn about use of variable before declaration? |
197 * RFE: 6425594 |
186 * RFE: 6425594 |
198 */ |
187 */ |
199 boolean useBeforeDeclarationWarning; |
188 boolean useBeforeDeclarationWarning; |
200 |
|
201 /** |
|
202 * Switch: generate warnings whenever an anonymous inner class that is convertible |
|
203 * to a lambda expression is found |
|
204 */ |
|
205 boolean identifyLambdaCandidate; |
|
206 |
189 |
207 /** |
190 /** |
208 * Switch: allow strings in switch? |
191 * Switch: allow strings in switch? |
209 */ |
192 */ |
210 boolean allowStringsInSwitch; |
193 boolean allowStringsInSwitch; |
608 } |
591 } |
609 |
592 |
610 /** Derived visitor method: attribute a statement or definition tree. |
593 /** Derived visitor method: attribute a statement or definition tree. |
611 */ |
594 */ |
612 public Type attribStat(JCTree tree, Env<AttrContext> env) { |
595 public Type attribStat(JCTree tree, Env<AttrContext> env) { |
613 return attribTree(tree, env, statInfo); |
596 Env<AttrContext> analyzeEnv = |
|
597 env.dup(tree, env.info.dup(env.info.scope.dupUnshared(env.info.scope.owner))); |
|
598 try { |
|
599 return attribTree(tree, env, statInfo); |
|
600 } finally { |
|
601 analyzer.analyzeIfNeeded(tree, analyzeEnv); |
|
602 } |
614 } |
603 } |
615 |
604 |
616 /** Attribute a list of expressions, returning a list of types. |
605 /** Attribute a list of expressions, returning a list of types. |
617 */ |
606 */ |
618 List<Type> attribExprs(List<JCExpression> trees, Env<AttrContext> env, Type pt) { |
607 List<Type> attribExprs(List<JCExpression> trees, Env<AttrContext> env, Type pt) { |
790 return t; |
779 return t; |
791 } |
780 } |
792 |
781 |
793 Type attribIdentAsEnumType(Env<AttrContext> env, JCIdent id) { |
782 Type attribIdentAsEnumType(Env<AttrContext> env, JCIdent id) { |
794 Assert.check((env.enclClass.sym.flags() & ENUM) != 0); |
783 Assert.check((env.enclClass.sym.flags() & ENUM) != 0); |
795 id.type = env.info.scope.owner.type; |
784 id.type = env.info.scope.owner.enclClass().type; |
796 id.sym = env.info.scope.owner; |
785 id.sym = env.info.scope.owner.enclClass(); |
797 return id.type; |
786 return id.type; |
798 } |
787 } |
799 |
788 |
800 public void visitClassDef(JCClassDecl tree) { |
789 public void visitClassDef(JCClassDecl tree) { |
801 // Local and anonymous classes have not been entered yet, so we need to |
790 // Local and anonymous classes have not been entered yet, so we need to |
2050 rsEnv, |
2039 rsEnv, |
2051 new ResultInfo(pkind, newMethodTemplate(syms.voidType, argtypes, typeargtypes))); |
2040 new ResultInfo(pkind, newMethodTemplate(syms.voidType, argtypes, typeargtypes))); |
2052 if (rsEnv.info.lastResolveVarargs()) |
2041 if (rsEnv.info.lastResolveVarargs()) |
2053 Assert.check(tree.constructorType.isErroneous() || tree.varargsElement != null); |
2042 Assert.check(tree.constructorType.isErroneous() || tree.varargsElement != null); |
2054 } |
2043 } |
2055 if (cdef == null && |
|
2056 !clazztype.isErroneous() && |
|
2057 clazztype.getTypeArguments().nonEmpty() && |
|
2058 findDiamonds) { |
|
2059 findDiamond(localEnv, tree, clazztype); |
|
2060 } |
|
2061 } |
2044 } |
2062 |
2045 |
2063 if (cdef != null) { |
2046 if (cdef != null) { |
2064 // We are seeing an anonymous class instance creation. |
2047 // We are seeing an anonymous class instance creation. |
2065 // In this case, the class instance creation |
2048 // In this case, the class instance creation |
2103 localEnv.info.isSerializable = true; |
2086 localEnv.info.isSerializable = true; |
2104 } |
2087 } |
2105 |
2088 |
2106 attribStat(cdef, localEnv); |
2089 attribStat(cdef, localEnv); |
2107 |
2090 |
2108 checkLambdaCandidate(tree, cdef.sym, clazztype); |
|
2109 |
|
2110 // If an outer instance is given, |
2091 // If an outer instance is given, |
2111 // prefix it to the constructor arguments |
2092 // prefix it to the constructor arguments |
2112 // and delete it from the new expression |
2093 // and delete it from the new expression |
2113 if (tree.encl != null && !clazztype.tsym.isInterface()) { |
2094 if (tree.encl != null && !clazztype.tsym.isInterface()) { |
2114 tree.args = tree.args.prepend(makeNullCheck(tree.encl)); |
2095 tree.args = tree.args.prepend(makeNullCheck(tree.encl)); |
2133 owntype = clazztype; |
2114 owntype = clazztype; |
2134 } |
2115 } |
2135 result = check(tree, owntype, KindSelector.VAL, resultInfo); |
2116 result = check(tree, owntype, KindSelector.VAL, resultInfo); |
2136 chk.validate(tree.typeargs, localEnv); |
2117 chk.validate(tree.typeargs, localEnv); |
2137 } |
2118 } |
2138 //where |
|
2139 void findDiamond(Env<AttrContext> env, JCNewClass tree, Type clazztype) { |
|
2140 JCTypeApply ta = (JCTypeApply)tree.clazz; |
|
2141 List<JCExpression> prevTypeargs = ta.arguments; |
|
2142 try { |
|
2143 //create a 'fake' diamond AST node by removing type-argument trees |
|
2144 ta.arguments = List.nil(); |
|
2145 ResultInfo findDiamondResult = new ResultInfo(KindSelector.VAL, |
|
2146 resultInfo.checkContext.inferenceContext().free(resultInfo.pt) ? Type.noType : pt()); |
|
2147 Type inferred = deferredAttr.attribSpeculative(tree, env, findDiamondResult).type; |
|
2148 Type polyPt = allowPoly ? |
|
2149 syms.objectType : |
|
2150 clazztype; |
|
2151 if (!inferred.isErroneous() && |
|
2152 (allowPoly && pt() == Infer.anyPoly ? |
|
2153 types.isSameType(inferred, clazztype) : |
|
2154 types.isAssignable(inferred, pt().hasTag(NONE) ? polyPt : pt(), types.noWarnings))) { |
|
2155 String key = types.isSameType(clazztype, inferred) ? |
|
2156 "diamond.redundant.args" : |
|
2157 "diamond.redundant.args.1"; |
|
2158 log.warning(tree.clazz.pos(), key, clazztype, inferred); |
|
2159 } |
|
2160 } finally { |
|
2161 ta.arguments = prevTypeargs; |
|
2162 } |
|
2163 } |
|
2164 |
|
2165 private void checkLambdaCandidate(JCNewClass tree, ClassSymbol csym, Type clazztype) { |
|
2166 if (allowLambda && |
|
2167 identifyLambdaCandidate && |
|
2168 clazztype.hasTag(CLASS) && |
|
2169 !pt().hasTag(NONE) && |
|
2170 types.isFunctionalInterface(clazztype.tsym)) { |
|
2171 Symbol descriptor = types.findDescriptorSymbol(clazztype.tsym); |
|
2172 int count = 0; |
|
2173 boolean found = false; |
|
2174 for (Symbol sym : csym.members().getSymbols()) { |
|
2175 if ((sym.flags() & SYNTHETIC) != 0 || |
|
2176 sym.isConstructor()) continue; |
|
2177 count++; |
|
2178 if (sym.kind != MTH || |
|
2179 !sym.name.equals(descriptor.name)) continue; |
|
2180 Type mtype = types.memberType(clazztype, sym); |
|
2181 if (types.overrideEquivalent(mtype, types.memberType(clazztype, descriptor))) { |
|
2182 found = true; |
|
2183 } |
|
2184 } |
|
2185 if (found && count == 1) { |
|
2186 log.note(tree.def, "potential.lambda.found"); |
|
2187 } |
|
2188 } |
|
2189 } |
|
2190 |
2119 |
2191 /** Make an attributed null check tree. |
2120 /** Make an attributed null check tree. |
2192 */ |
2121 */ |
2193 public JCExpression makeNullCheck(JCExpression arg) { |
2122 public JCExpression makeNullCheck(JCExpression arg) { |
2194 // optimization: X.this is never null; skip null check |
2123 // optimization: X.this is never null; skip null check |