protected void outputEnumItemsAsConstants(
      List<EnumItemResult> results,
      DeclarationsHolder out,
      Signatures signatures,
      Identifier libraryClassName,
      boolean hasEnumClass) {

    for (EnumItemResult er : results) {
      try {
        if (er.errorElement != null) {
          out.addDeclaration(er.errorElement);
          continue;
        }
        String itemName =
            result.typeConverter.getValidJavaIdentifierString(ident(er.originalItem.getName()));
        Declaration ct =
            outputConstant(
                itemName,
                result.typeConverter.convertExpressionToJava(
                    er.unconvertedValue, libraryClassName, true),
                signatures,
                er.originalItem,
                "enum item",
                libraryClassName,
                hasEnumClass,
                true,
                true,
                true);
        if (!result.config.noComments)
          if (ct != null && hasEnumClass) {
            String c = ct.getCommentBefore();
            ct.setCommentBefore(er.originalItem.getCommentBefore());
            ct.addToCommentBefore(c);
          }
        out.addDeclaration(ct);
      } catch (Exception ex) {
        out.addDeclaration(skipDeclaration(er.originalItem, ex.toString()));
      }
    }
  }
  protected List<EnumItemResult> getEnumValuesAndCommentsByName(
      Enum e, Signatures signatures, Identifier libraryClassName) {
    List<EnumItemResult> ret = new ArrayList<EnumItemResult>();
    Integer lastAdditiveValue = null;
    Expression lastRefValue = null;
    boolean failedOnceForThisEnum = false;
    for (com.ochafik.lang.jnaerator.parser.Enum.EnumItem item : e.getItems()) {
      EnumItemResult res = new EnumItemResult();
      res.originalItem = item;
      try {
        if (item.getArguments().isEmpty()) {
          // no explicit value
          if (lastRefValue == null) {
            if (lastAdditiveValue != null) {
              lastAdditiveValue++;
              res.unconvertedValue = expr(lastAdditiveValue);
            } else {
              if (item == e.getItems().get(0)) {
                lastAdditiveValue = 0;
                res.unconvertedValue = expr(lastAdditiveValue);
              } else res.unconvertedValue = null;
            }
          } else {
            // has a last reference value
            if (lastAdditiveValue != null) lastAdditiveValue++;
            else lastAdditiveValue = 1;

            res.unconvertedValue =
                expr(lastRefValue.clone(), Expression.BinaryOperator.Plus, expr(lastAdditiveValue));
          }
        } else {
          // has an explicit value
          failedOnceForThisEnum = false; // reset skipping
          lastAdditiveValue = null;
          lastRefValue = item.getArguments().get(0);
          res.unconvertedValue = lastRefValue;
          if (lastRefValue instanceof Expression.Constant) {
            try {
              lastAdditiveValue = ((Expression.Constant) lastRefValue).asInteger();
              lastRefValue = null;
            } catch (Exception ex) {
            }
          }
        }

        res.convertedValue =
            result
                .typeConverter
                .convertExpressionToJava(res.unconvertedValue, libraryClassName, true)
                .getFirst();
      } catch (Exception ex) {
        failedOnceForThisEnum = true;
        res.exceptionMessage = ex.toString();
      }
      failedOnceForThisEnum = failedOnceForThisEnum || res.errorElement != null;
      if (failedOnceForThisEnum) res.errorElement = skipDeclaration(item);

      ret.add(res);
    }
    return ret;
  }