public void visit(BindingVisitor visitor) {
    NotNullLazyValue<Boolean> hasClassLevelPropertyAnnotation = NotNullLazyValue.lazy(() -> hasClassLevelPropertyAnnotation());

    for (PsiField field : myPsiClass.getAllFields()) {
      if (field.hasModifierProperty(PsiModifier.STATIC) ||
          field.hasModifierProperty(PsiModifier.VOLATILE)) {
        continue;
      }

      NullableLazyValue<PsiMethod> getter = NullableLazyValue.lazyNullable(() -> PropertyUtilBase.findGetterForField(field));
      NullableLazyValue<PsiMethod> setter = NullableLazyValue.lazyNullable(() -> PropertyUtilBase.findSetterForField(field));

      if (!field.hasModifierProperty(PsiModifier.PUBLIC) && (getter.getValue() == null || setter.getValue() == null)) {
        continue;
      }

      final PsiAnnotation requiredAnnotation = findAnnotationForField(RequiredElement.class, field, getter, setter);
      BindingVisitor.RequiredFlag required = BindingVisitor.RequiredFlag.NOT_REQUIRED;
      if (requiredAnnotation != null) {
        required = PsiUtil.getAnnotationBooleanAttribute(requiredAnnotation, "allowEmpty") ?
                   BindingVisitor.RequiredFlag.REQUIRED_ALLOW_EMPTY : BindingVisitor.RequiredFlag.REQUIRED;
      }

      final PsiAnnotation attributeAnnotation = findAnnotationForField(Attribute.class, field, getter, setter);
      if (attributeAnnotation != null) {
        String fieldName = PsiUtil.getAnnotationStringAttribute(attributeAnnotation, "value", field.getName());
        if (fieldName != null) {
          visitor.visitAttribute(field, fieldName, required);
        }
      }
      else if (hasClassLevelPropertyAnnotation.get()) {
        visitor.visitAttribute(field, field.getName(), required);
      }
      else {
        final PsiAnnotation tagAnno = findAnnotationForField(Tag.class, field, getter, setter);
        final PsiAnnotation collectionAnnotation = findAnnotationForField(XCollection.class, field, getter, setter);
        //final PsiAnnotation colAnno = modifierList.findAnnotation(Collection.class.getName()); // todo

        String fieldName = field.getName();
        final String tagName;
        if (tagAnno != null) {
          tagName = PsiUtil.getAnnotationStringAttribute(tagAnno, "value", fieldName);
        }
        else {
          final PsiAnnotation propAnno = findAnnotationForField(Property.class, field, getter, setter);
          tagName = propAnno != null && PsiUtil.getAnnotationBooleanAttribute(propAnno, "surroundWithTag") ? Constants.OPTION : null;
        }

        if (tagName != null && collectionAnnotation == null) {
          visitor.visitTagOrProperty(field, tagName, required);
        }
        else if (collectionAnnotation != null) {
          visitor.visitXCollection(field, tagName, collectionAnnotation, required);
        }
      }
    }
  }
public void visit(BindingVisitor visitor)