package com.redhat.ceylon.compiler.js;

import com.redhat.ceylon.compiler.typechecker.model.Scope;
import com.redhat.ceylon.compiler.typechecker.tree.Tree.BaseMemberExpression;
import com.redhat.ceylon.compiler.typechecker.tree.Tree.Block;
import com.redhat.ceylon.compiler.typechecker.tree.Tree.MethodDefinition;
import com.redhat.ceylon.compiler.typechecker.tree.Visitor;

/** This visitor is used to check if a block of code contains method definitions which use expressions
 * declared in the block's scope, to determine if the block should be enclosed in a function.
 * 
 * @author Enrique Zamudio
 */
public class EnclosingFunctionVisitor extends Visitor {

    private Scope mainScope;
    private boolean check;
    private boolean enclose;

    /** Determines whether the specified block should be enclosed in a function. */
    public boolean encloseBlock(Block block) {
        enclose = false;
        check = false;
        if (block.getStatements().isEmpty()) {
            return false;
        } else {
            mainScope = block.getStatements().get(0).getScope();
        }
        block.visit(this);
        mainScope = null;
        return enclose;
    }

    /** Enables checking of base member expressions. */
    public void visit(MethodDefinition that) {
        check = true;
        super.visit(that);
    }

    /** Checks if the expression is used in a scope different from the main one, and if the declaration
     * of this expression is in the main scope. */
    public void visit(BaseMemberExpression that) {
        if (check && !enclose) {
            enclose = that.getScope()!=mainScope && that.getDeclaration().getContainer()==mainScope;
        }
        super.visit(that);
    }

}

@@ -83,97 +83,23 @@
 ker.
-model.Scope;%0Aimport com.redhat.ceylon.compiler.typechecker.tree.Tree.BaseMemberExpression
+tree.Tree.Block
 ;%0Aim
@@ -144,37 +144,43 @@
 ecker.tree.Tree.
-Block
+Declaration
 ;%0Aimport com.red
@@ -221,32 +221,25 @@
 ee.Tree.
-MethodDefinition
+Statement
 ;%0Aimport
@@ -586,94 +586,8 @@
  %7B%0A%0A
-    private Scope mainScope;%0A    private boolean check;%0A    private boolean enclose;%0A%0A
     
@@ -725,161 +725,101 @@
     
-enclose = false;%0A        check = false;%0A        if (block.getStatements().isEmpty()) %7B%0A            return false;%0A        %7D else %7B%0A            mainScope =
+// just check if the block contains a captured declaration%0A        for (Statement statement :
  blo
@@ -840,27 +840,11 @@
 ts()
-.get(0).getScope();
+) %7B
 %0A   
@@ -852,592 +852,200 @@
     
-%7D%0A
     
-    block.visit(this);%0A        mainScope = null;%0A        return enclose;%0A    %7D%0A%0A    /** Enables checking of base member expressions. */%0A    public void visit(MethodDefinition that) %7B%0A        check = true;%0A        super.visit(that);%0A    %7D%0A%0A    /** Checks if the expression is used in a scope different from the main one, and if the declaration%0A     * of this expression is in the main scope. */%0A    public void visit(BaseMemberExpression that) %7B%0A        if (check && !enclose) %7B%0A            enclose = that.getScope()!=mainScope && that.getDeclaration().getContainer()==mainScope;
+if (statement instanceof Declaration) %7B%0A                if (((Declaration) statement).getDeclarationModel().isCaptured()) %7B%0A                    return true;%0A                %7D%0A            %7D
 %0A   
@@ -1063,25 +1063,20 @@
     
-super.visit(that)
+return false
 ;%0A  

fix #132 by relying on "captured" flag instead of analyzing scopes