ITraitVisitor declareVariable(
      VariableNode varNode,
      DefinitionBase varDef,
      boolean is_static,
      boolean is_const,
      Object initializer) {
    final ICompilerProject project = this.classScope.getProject();
    Name var_name = varDef.getMName(project);

    TypeDefinitionBase typeDef = varDef.resolveType(project);
    Name var_type = typeDef != null ? typeDef.getMName(project) : null;

    int trait_kind = is_const ? TRAIT_Const : TRAIT_Var;

    LexicalScope ls = is_static ? this.classStaticScope : this.classScope;

    ls.declareVariableName(var_name);

    ITraitVisitor tv =
        ls.traitsVisitor.visitSlotTrait(
            trait_kind, var_name, ITraitsVisitor.RUNTIME_SLOT, var_type, initializer);

    if (!is_static)
      if (varDef.getNamespaceReference()
          instanceof NamespaceDefinition.IProtectedNamespaceDefinition)
        this.iinfo.flags |= ABCConstants.CLASS_FLAG_protected;

    SemanticUtils.checkScopedToDefaultNamespaceProblem(
        this.classScope, varNode, varDef, this.className.getBaseName());

    return tv;
  }
  /** Declare a variable. */
  @Override
  void declareVariable(VariableNode var) {
    verifyVariableModifiers(var);

    VariableDefinition varDef = (VariableDefinition) var.getDefinition();

    boolean is_static = var.hasModifier(ASModifier.STATIC);
    boolean is_const = SemanticUtils.isConst(var, classScope.getProject());

    final ICompilerProject project = this.classScope.getProject();

    ICodeGenerator codeGenerator = classScope.getGenerator();
    IExpressionNode assignedValueNode = var.getAssignedValueNode();
    IConstantValue constantValue = codeGenerator.generateConstantValue(assignedValueNode, project);

    //  initializer is null if no constant value
    //  can be generated, and null is the correct value for "no value."
    Object initializer = constantValue != null ? constantValue.getValue() : null;

    // Reducing the constant value may have produced problems in the
    // LexicalScope used for constant reduction. Transfer them over
    // to the LexicalScope for this class.
    Collection<ICompilerProblem> problems =
        constantValue != null ? constantValue.getProblems() : null;
    if (problems != null) classScope.addProblems(problems);

    final MethodBodySemanticChecker checker =
        MethodBodySemanticCheckerFactory.getChecker(this.classScope); // CO-5148

    DefinitionBase varType = (DefinitionBase) varDef.resolveType(project);

    Object transformed_initializer = null;

    if ((initializer != null) && (varType != null)) {
      transformed_initializer =
          checker
              .checkInitialValue(
                  var,
                  new Binding(null, varType.getMName(this.classScope.getProject()), varType),
                  new PooledValue(initializer))
              .getValue();
    } else {
      transformed_initializer = initializer;
    }

    ITraitVisitor tv = declareVariable(var, varDef, is_static, is_const, transformed_initializer);
    if (is_static) this.classStaticScope.processMetadata(tv, getAllMetaTags(varDef));
    else this.classScope.processMetadata(tv, getAllMetaTags(varDef));
    tv.visitEnd();

    //  Generate variable initializers and append them to the
    //  proper initialization list.
    if (transformed_initializer == null && var.getAssignedValueNode() != null) {
      // Emit initialization instructions for non-static vars.  Static var
      // instructions will be emitted during finishClassDefinition()
      if (is_static) staticVariableInitializers.add(var);
      else generateInstructions(var, false);
    } else {
      checker.checkClassField(var, is_static);
      //  Massive kludge -- grovel over chained variable decls and add them one by one
      for (int i = 0; i < var.getChildCount(); i++) {
        IASNode candidate = var.getChild(i);

        if (candidate instanceof VariableNode) {
          declareVariable((VariableNode) candidate);
        }
      }
    }
  }