langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java
changeset 19933 5182bc65845b
parent 19502 f30b3ef165ea
child 19941 8b91e8eb2d20
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java	Mon Sep 09 17:36:23 2013 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java	Mon Sep 09 23:13:45 2013 +0200
@@ -224,7 +224,6 @@
         }
         try {
             new AliveAnalyzer().analyzeTree(env, that, make);
-            new LambdaFlowAnalyzer().analyzeTree(env, that, make);
         } finally {
             if (!speculative) {
                 log.popDiagnosticHandler(diagHandler);
@@ -232,6 +231,23 @@
         }
     }
 
+    public List<Type> analyzeLambdaThrownTypes(Env<AttrContext> env, JCLambda that, TreeMaker make) {
+        //we need to disable diagnostics temporarily; the problem is that if
+        //a lambda expression contains e.g. an unreachable statement, an error
+        //message will be reported and will cause compilation to skip the flow analyis
+        //step - if we suppress diagnostics, we won't stop at Attr for flow-analysis
+        //related errors, which will allow for more errors to be detected
+        Log.DiagnosticHandler diagHandler = new Log.DiscardDiagnosticHandler(log);
+        try {
+            new AssignAnalyzer().analyzeTree(env, that, make);
+            LambdaFlowAnalyzer flowAnalyzer = new LambdaFlowAnalyzer();
+            flowAnalyzer.analyzeTree(env, that, make);
+            return flowAnalyzer.inferredThrownTypes;
+        } finally {
+            log.popDiagnosticHandler(diagHandler);
+        }
+    }
+
     /**
      * Definite assignment scan mode
      */
@@ -1318,27 +1334,35 @@
      * Specialized pass that performs inference of thrown types for lambdas.
      */
     class LambdaFlowAnalyzer extends FlowAnalyzer {
+        List<Type> inferredThrownTypes;
+        boolean inLambda;
         @Override
         public void visitLambda(JCLambda tree) {
-            if (tree.type != null &&
-                    tree.type.isErroneous()) {
+            if ((tree.type != null &&
+                    tree.type.isErroneous()) || inLambda) {
                 return;
             }
             List<Type> prevCaught = caught;
             List<Type> prevThrown = thrown;
             ListBuffer<FlowPendingExit> prevPending = pendingExits;
+            inLambda = true;
             try {
                 pendingExits = ListBuffer.lb();
                 caught = List.of(syms.throwableType);
                 thrown = List.nil();
                 scan(tree.body);
-                tree.inferredThrownTypes = thrown;
+                inferredThrownTypes = thrown;
             } finally {
                 pendingExits = prevPending;
                 caught = prevCaught;
                 thrown = prevThrown;
+                inLambda = false;
             }
         }
+        @Override
+        public void visitClassDef(JCClassDecl tree) {
+            //skip
+        }
     }
 
     /**