public void validateDeep(@NotNull YAMLValue value, @NotNull ProblemsHolder problemsHolder) {
    validateValue(value, problemsHolder);

    // TODO a case for sequence

    if (value instanceof YAMLMapping mapping) {

      Collection<YAMLKeyValue> keyValues = mapping.getKeyValues();

      // check for missing keys
      // TODO reuse with YamlMissingKeysInspectionBase
      final Collection<String> missingKeys =
        computeMissingFields(keyValues.stream().map(it -> it.getKeyText().trim()).collect(Collectors.toSet()));

      if (!missingKeys.isEmpty()) {
        String msg = YAMLBundle.message("YamlMissingKeysInspectionBase.missing.keys", String.join(", ", missingKeys));
        problemsHolder.registerProblem(mapping, msg, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
      }

      for (YAMLKeyValue keyValue : keyValues) {
        String featureName = keyValue.getKeyText().trim();

        if (featureName.isEmpty()) {
          continue;
        }

        Field feature = findFeatureByName(featureName);
        if (feature == null) {
          String msg = YAMLBundle.message("YamlUnknownKeysInspectionBase.unknown.key", keyValue.getKeyText());
          final PsiElement key = keyValue.getKey();
          assert key != null;
          problemsHolder.registerProblem(key, msg, ProblemHighlightType.LIKE_UNKNOWN_SYMBOL);
          continue;
        }

        YAMLValue subValue = keyValue.getValue();

        if (subValue == null) {
          if (!feature.isEmptyValueAllowed()) {
            // TODO report problem
          }

          continue;
        }

        final Field.Relation relation;
        if (subValue instanceof YAMLScalar) {
          relation = Field.Relation.SCALAR_VALUE;
        }
        else if (subValue instanceof YAMLSequence) {
          relation = Field.Relation.SEQUENCE_ITEM;
        }
        else {
          relation = Field.Relation.OBJECT_CONTENTS;
        }

        YamlMetaType subType = feature.getType(relation);

        if (!(subValue instanceof YAMLSequence)) {
          subType.validateDeep(subValue, problemsHolder);
        }
        else {
          List<YAMLSequenceItem> sequenceItems = ((YAMLSequence)subValue).getItems();
          for (YAMLSequenceItem item : sequenceItems) {
            YAMLValue itemValue = item.getValue();

            if (itemValue == null) {
              if (!feature.isEmptyValueAllowed()) {
                // TODO report problem
              }

              continue;
            }

            subType.validateDeep(itemValue, problemsHolder);
          }
        }
      }
    }
  }
public void validateDeep(@NotNull YAMLValue value, @NotNull ProblemsHolder problemsHolder)