27 |
27 |
28 package com.sun.tools.javac.comp; |
28 package com.sun.tools.javac.comp; |
29 |
29 |
30 import java.util.HashMap; |
30 import java.util.HashMap; |
31 |
31 |
|
32 import com.sun.source.tree.LambdaExpressionTree.BodyKind; |
32 import com.sun.tools.javac.code.*; |
33 import com.sun.tools.javac.code.*; |
33 import com.sun.tools.javac.code.Scope.WriteableScope; |
34 import com.sun.tools.javac.code.Scope.WriteableScope; |
34 import com.sun.tools.javac.tree.*; |
35 import com.sun.tools.javac.tree.*; |
35 import com.sun.tools.javac.util.*; |
36 import com.sun.tools.javac.util.*; |
36 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; |
37 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; |
222 //related errors, which will allow for more errors to be detected |
223 //related errors, which will allow for more errors to be detected |
223 if (!speculative) { |
224 if (!speculative) { |
224 diagHandler = new Log.DiscardDiagnosticHandler(log); |
225 diagHandler = new Log.DiscardDiagnosticHandler(log); |
225 } |
226 } |
226 try { |
227 try { |
227 new AliveAnalyzer().analyzeTree(env, that, make); |
228 new LambdaAliveAnalyzer().analyzeTree(env, that, make); |
228 } finally { |
229 } finally { |
229 if (!speculative) { |
230 if (!speculative) { |
230 log.popDiagnosticHandler(diagHandler); |
231 log.popDiagnosticHandler(diagHandler); |
231 } |
232 } |
232 } |
233 } |
239 //message will be reported and will cause compilation to skip the flow analyis |
240 //message will be reported and will cause compilation to skip the flow analyis |
240 //step - if we suppress diagnostics, we won't stop at Attr for flow-analysis |
241 //step - if we suppress diagnostics, we won't stop at Attr for flow-analysis |
241 //related errors, which will allow for more errors to be detected |
242 //related errors, which will allow for more errors to be detected |
242 Log.DiagnosticHandler diagHandler = new Log.DiscardDiagnosticHandler(log); |
243 Log.DiagnosticHandler diagHandler = new Log.DiscardDiagnosticHandler(log); |
243 try { |
244 try { |
244 new AssignAnalyzer() { |
245 new LambdaAssignAnalyzer(env).analyzeTree(env, that); |
245 WriteableScope enclosedSymbols = WriteableScope.create(env.enclClass.sym); |
|
246 @Override |
|
247 public void visitVarDef(JCVariableDecl tree) { |
|
248 enclosedSymbols.enter(tree.sym); |
|
249 super.visitVarDef(tree); |
|
250 } |
|
251 @Override |
|
252 protected boolean trackable(VarSymbol sym) { |
|
253 return enclosedSymbols.includes(sym) && |
|
254 sym.owner.kind == MTH; |
|
255 } |
|
256 }.analyzeTree(env, that); |
|
257 LambdaFlowAnalyzer flowAnalyzer = new LambdaFlowAnalyzer(); |
246 LambdaFlowAnalyzer flowAnalyzer = new LambdaFlowAnalyzer(); |
258 flowAnalyzer.analyzeTree(env, that, make); |
247 flowAnalyzer.analyzeTree(env, that, make); |
259 return flowAnalyzer.inferredThrownTypes; |
248 return flowAnalyzer.inferredThrownTypes; |
260 } finally { |
249 } finally { |
261 log.popDiagnosticHandler(diagHandler); |
250 log.popDiagnosticHandler(diagHandler); |
1335 pendingExits = null; |
1324 pendingExits = null; |
1336 Flow.this.make = null; |
1325 Flow.this.make = null; |
1337 this.thrown = this.caught = null; |
1326 this.thrown = this.caught = null; |
1338 this.classDef = null; |
1327 this.classDef = null; |
1339 } |
1328 } |
|
1329 } |
|
1330 } |
|
1331 |
|
1332 /** |
|
1333 * Specialized pass that performs reachability analysis on a lambda |
|
1334 */ |
|
1335 class LambdaAliveAnalyzer extends AliveAnalyzer { |
|
1336 |
|
1337 boolean inLambda; |
|
1338 |
|
1339 @Override |
|
1340 public void visitReturn(JCReturn tree) { |
|
1341 //ignore lambda return expression (which might not even be attributed) |
|
1342 recordExit(new PendingExit(tree)); |
|
1343 } |
|
1344 |
|
1345 @Override |
|
1346 public void visitLambda(JCLambda tree) { |
|
1347 if (inLambda || tree.getBodyKind() == BodyKind.EXPRESSION) { |
|
1348 return; |
|
1349 } |
|
1350 inLambda = true; |
|
1351 try { |
|
1352 super.visitLambda(tree); |
|
1353 } finally { |
|
1354 inLambda = false; |
|
1355 } |
|
1356 } |
|
1357 |
|
1358 @Override |
|
1359 public void visitClassDef(JCClassDecl tree) { |
|
1360 //skip |
|
1361 } |
|
1362 } |
|
1363 |
|
1364 /** |
|
1365 * Specialized pass that performs DA/DU on a lambda |
|
1366 */ |
|
1367 class LambdaAssignAnalyzer extends AssignAnalyzer { |
|
1368 WriteableScope enclosedSymbols; |
|
1369 boolean inLambda; |
|
1370 |
|
1371 LambdaAssignAnalyzer(Env<AttrContext> env) { |
|
1372 enclosedSymbols = WriteableScope.create(env.enclClass.sym); |
|
1373 } |
|
1374 |
|
1375 @Override |
|
1376 public void visitLambda(JCLambda tree) { |
|
1377 if (inLambda) { |
|
1378 return; |
|
1379 } |
|
1380 inLambda = true; |
|
1381 try { |
|
1382 super.visitLambda(tree); |
|
1383 } finally { |
|
1384 inLambda = false; |
|
1385 } |
|
1386 } |
|
1387 |
|
1388 @Override |
|
1389 public void visitVarDef(JCVariableDecl tree) { |
|
1390 enclosedSymbols.enter(tree.sym); |
|
1391 super.visitVarDef(tree); |
|
1392 } |
|
1393 @Override |
|
1394 protected boolean trackable(VarSymbol sym) { |
|
1395 return enclosedSymbols.includes(sym) && |
|
1396 sym.owner.kind == MTH; |
|
1397 } |
|
1398 |
|
1399 @Override |
|
1400 public void visitClassDef(JCClassDecl tree) { |
|
1401 //skip |
1340 } |
1402 } |
1341 } |
1403 } |
1342 |
1404 |
1343 /** |
1405 /** |
1344 * Specialized pass that performs inference of thrown types for lambdas. |
1406 * Specialized pass that performs inference of thrown types for lambdas. |