// TODO handle local variables
 private void checkForFinal(final Expression expression, VariableExpression ve) {
   Variable v = ve.getAccessedVariable();
   boolean isFinal = isFinal(v.getModifiers());
   boolean isParameter = v instanceof Parameter;
   if (isFinal && isParameter) {
     addError("Cannot assign a value to final variable '" + v.getName() + "'", expression);
   }
 }
  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);
  }
 protected Expression transformVariableExpression(VariableExpression ve) {
   Variable v = ve.getAccessedVariable();
   if (v != null && v instanceof DynamicVariable) {
     Expression result = findStaticFieldOrPropAccessorImportFromModule(v.getName());
     if (result != null) {
       setSourcePosition(result, ve);
       if (inAnnotation) {
         result = transformInlineConstants(result);
       }
       return result;
     }
   }
   return ve;
 }
  private Variable checkVariableNameForDeclaration(String name, Expression expression) {
    if ("super".equals(name) || "this".equals(name)) return null;

    VariableScope scope = currentScope;
    Variable var = new DynamicVariable(name, currentScope.isInStaticContext());
    // try to find a declaration of a variable
    while (true) {
      Variable var1;
      var1 = scope.getDeclaredVariable(var.getName());

      if (var1 != null) {
        var = var1;
        break;
      }

      var1 = scope.getReferencedLocalVariable(var.getName());
      if (var1 != null) {
        var = var1;
        break;
      }

      var1 = scope.getReferencedClassVariable(var.getName());
      if (var1 != null) {
        var = var1;
        break;
      }

      ClassNode classScope = scope.getClassScope();
      if (classScope != null) {
        Variable member = findClassMember(classScope, var.getName());
        if (member != null) {
          boolean staticScope = currentScope.isInStaticContext() || isSpecialConstructorCall;
          boolean staticMember = member.isInStaticContext();
          // We don't allow a static context (e.g. a static method) to access
          // a non-static variable (e.g. a non-static field).
          if (!(staticScope && !staticMember)) var = member;
        }
        break;
      }
      scope = scope.getParent();
    }

    VariableScope end = scope;

    scope = currentScope;
    while (scope != end) {
      if (end.isClassScope()
          || (end.isReferencedClassVariable(name) && end.getDeclaredVariable(name) == null)) {
        scope.putReferencedClassVariable(var);
      } else {
        // var.setClosureSharedVariable(var.isClosureSharedVariable() || inClosure);
        scope.putReferencedLocalVariable(var);
      }
      scope = scope.getParent();
    }

    return var;
  }
  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);
  }