void (@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); } } } } }