public void visitClosureExpression(ClosureExpression expression) {
    pushState();

    expression.setVariableScope(currentScope);

    if (expression.isParameterSpecified()) {
      Parameter[] parameters = expression.getParameters();
      for (Parameter parameter : parameters) {
        parameter.setInStaticContext(currentScope.isInStaticContext());
        if (parameter.hasInitialExpression()) {
          parameter.getInitialExpression().visit(this);
        }
        declare(parameter, expression);
      }
    } else if (expression.getParameters() != null) {
      Parameter var = new Parameter(ClassHelper.OBJECT_TYPE, "it");
      var.setInStaticContext(currentScope.isInStaticContext());
      currentScope.putDeclaredVariable(var);
    }

    super.visitClosureExpression(expression);
    markClosureSharedVariables();

    popState();
  }
  private void checkVariableContextAccess(Variable v, Expression expr) {
    if (inPropertyExpression || v.isInStaticContext() || !currentScope.isInStaticContext()) return;

    String msg =
        v.getName()
            + " is declared in a dynamic context, but you tried to"
            + " access it from a static context.";
    addError(msg, expr);

    // declare a static variable to be able to continue the check
    DynamicVariable v2 = new DynamicVariable(v.getName(), currentScope.isInStaticContext());
    currentScope.putDeclaredVariable(v2);
  }
  private void declare(Variable var, ASTNode expr) {
    String scopeType = "scope";
    String variableType = "variable";

    if (expr.getClass() == FieldNode.class) {
      scopeType = "class";
      variableType = "field";
    } else if (expr.getClass() == PropertyNode.class) {
      scopeType = "class";
      variableType = "property";
    }

    StringBuilder msg = new StringBuilder();
    msg.append("The current ").append(scopeType);
    msg.append(" already contains a ").append(variableType);
    msg.append(" of the name ").append(var.getName());

    if (currentScope.getDeclaredVariable(var.getName()) != null) {
      addError(msg.toString(), expr);
      return;
    }

    for (VariableScope scope = currentScope.getParent(); scope != null; scope = scope.getParent()) {
      // if we are in a class and no variable is declared until
      // now, then we can break the loop, because we are allowed
      // to declare a variable of the same name as a class member
      if (scope.getClassScope() != null) break;

      if (scope.getDeclaredVariable(var.getName()) != null) {
        // variable already declared
        addError(msg.toString(), expr);
        break;
      }
    }
    // declare the variable even if there was an error to allow more checks
    currentScope.putDeclaredVariable(var);
  }