package com.redhat.ceylon.compiler.js.util;

import com.redhat.ceylon.compiler.typechecker.tree.Node;
import com.redhat.ceylon.compiler.typechecker.tree.Tree;
import com.redhat.ceylon.compiler.typechecker.tree.Visitor;
import com.redhat.ceylon.model.typechecker.model.Scope;

public class ContinueBreakVisitor extends Visitor {

    private boolean breaks;
    private boolean continues;
    private boolean returns;
    private final Scope scope;
    private final JsIdentifierNames names;
    private String bname;
    private String cname;
    private String rname;

    public ContinueBreakVisitor(Node n, JsIdentifierNames names) {
        scope = n.getScope();
        this.names = names;
        n.visit(this);
    }

    public void visit(Tree.Break n) {
        if (n.getScope() == scope) {
            if (bname == null) {
                bname = names.createTempVariable();
            }
            breaks = true;
        }
        super.visit(n);
    }
    public void visit(Tree.Continue n) {
        if (n.getScope() == scope) {
            if (cname == null) {
                cname = names.createTempVariable();
            }
            continues = true;
        }
        super.visit(n);
    }
    public void visit(Tree.Return n) {
        if (n.getScope() == scope) {
            returns = true;
        }
        super.visit(n);
    }

    public Scope getScope() {
        return scope;
    }
    public boolean isContinues() {
        return continues;
    }
    public boolean isReturns() {
        return returns;
    }
    public boolean isBreaks() {
        return breaks;
    }

    public String getContinueName() {
        return cname;
    }
    public String getBreakName() {
        return bname;
    }
    public String getReturnName() {
        if (rname == null) {
            rname = names.createTempVariable();
        }
        return rname;
    }
}

@@ -38,16 +38,51 @@
 .util;%0A%0A
+import java.util.IdentityHashMap;%0A%0A
 import c
@@ -111,29 +111,34 @@
 ler.
-typechecker.tree.Node
+js.BlockWithCaptureVisitor
 ;%0Aim
@@ -601,16 +601,158 @@
 g rname;
+%0A    private int level;%0A    private boolean ignore;%0A    private final IdentityHashMap%3CTree.Directive, Boolean%3E dirs = new IdentityHashMap%3C%3E();
 %0A%0A    pu
@@ -781,12 +781,18 @@
 tor(
-Node
+Tree.Block
  n, 
@@ -938,14 +938,17 @@
 ee.B
-reak n
+lock that
 ) %7B%0A
@@ -959,33 +959,300 @@
     
-if (n.getScope() == scope
+level++;%0A        if (level%3E1) %7B%0A            ignore=new BlockWithCaptureVisitor(that).hasCapture();%0A        %7D%0A        super.visit(that);%0A        ignore=false;%0A        level--;%0A    %7D%0A    public void visit(Tree.Break n) %7B%0A        if (ignore) %7B%0A            return;%0A        %7D%0A        if (level %3C 3
 ) %7B%0A
@@ -1369,32 +1369,63 @@
  breaks = true;%0A
+            dirs.put(n, true);%0A
         %7D%0A      
@@ -1501,37 +1501,77 @@
     if (
-n.getScope() == scope
+ignore) %7B%0A            return;%0A        %7D%0A        if (level %3C 3
 ) %7B%0A    
@@ -1687,32 +1687,63 @@
 ntinues = true;%0A
+            dirs.put(n, true);%0A
         %7D%0A      
@@ -1821,29 +1821,69 @@
 if (
-n.getScope() == scope
+ignore) %7B%0A            return;%0A        %7D%0A        if (level %3C 3
 ) %7B%0A
@@ -1943,32 +1943,126 @@
 isit(n);%0A    %7D%0A%0A
+    public boolean belongs(Tree.Directive dir) %7B%0A        return dirs.containsKey(dir);%0A    %7D%0A%0A
     public Scope

refactor for #589