// Path: src/com/github/tinselspoon/intellij/kubernetes/KubernetesYamlPsiUtil.java
// public final class KubernetesYamlPsiUtil {
// 
//     /** Static class private constructor. */
//     private KubernetesYamlPsiUtil() {
//         // no construction
//     }
// 
//     /**
//      * Find the {@link ResourceTypeKey} for the current document.
//      *
//      * @param element an element within the document to check.
//      * @return the resource type key, or {@code null} if the "apiVersion" and "kind" fields are not present.
//      */
//     @Nullable
//     public static ResourceTypeKey findResourceKey(final PsiElement element) {
//         // Get the top-level mapping
//         final YAMLMapping topLevelMapping = getTopLevelMapping(element);
//         final String apiVersion = getValueText(topLevelMapping, "apiVersion");
//         final String kind = getValueText(topLevelMapping, "kind");
//         if (apiVersion != null && kind != null) {
//             return new ResourceTypeKey(apiVersion, kind);
//         } else {
//             return null;
//         }
//     }
// 
//     /**
//      * Gets the top-level mapping in the document, if present.
//      *
//      * @param element an element within the document.
//      * @return the top-level mapping, or {@code null} if one is not defined (e.g. in an empty document).
//      */
//     @Nullable
//     public static YAMLMapping getTopLevelMapping(final PsiElement element) {
//         final YAMLDocument document = PsiTreeUtil.getParentOfType(element, YAMLDocument.class);
//         if (document != null) {
//             final YAMLValue topLevelValue = document.getTopLevelValue();
//             if (topLevelValue instanceof YAMLMapping) {
//                 return (YAMLMapping) topLevelValue;
//             }
//         }
//         return null;
//     }
// 
//     /**
//      * Gets the text of the value held by the given key within a mapping.
//      *
//      * @param mapping the mapping to search through.
//      * @param key the key to search for.
//      * @return the trimmed text value of the key, or {@code null} if the mapping is null or the key was not found.
//      */
//     @Nullable
//     public static String getValueText(@Nullable final YAMLMapping mapping, @NotNull final String key) {
//         return Optional.ofNullable(mapping).map(m -> m.getKeyValueByKey(key)).map(YAMLKeyValue::getValueText).map(String::trim).orElse(null);
//     }
// 
//     /**
//      * Determines whether the element is within a Kubernetes YAML file. This is done by checking for the presence of "apiVersion" or "kind" as top-level keys within the first document of the file.
//      *
//      * @param element an element within the file to check.
//      * @return true if the element is within A Kubernetes YAML file, otherwise, false.
//      */
//     public static boolean isKubernetesFile(final PsiElement element) {
//         final PsiFile file = element.getContainingFile();
//         if (file instanceof YAMLFile) {
//             final Collection<YAMLKeyValue> keys = YAMLUtil.getTopLevelKeys((YAMLFile) file);
//             return keys.stream().map(YAMLKeyValue::getKeyText).anyMatch(s -> "apiVersion".equals(s) || "kind".equals(s));
//         }
//         return false;
//     }
// 
//     /**
//      * Find the corresponding {@link Model} object that represents the value of a given {@link YAMLKeyValue}.
//      *
//      * @param modelProvider the model provider to use for looking up schema resources.
//      * @param resourceKey the top-level key of the resource.
//      * @param keyValue the {@code YAMLKeyValue} to search back from.
//      * @return the corresponding model or {@code null} if one cannot be located.
//      */
//     @Nullable
//     public static Model modelForKey(final ModelProvider modelProvider, final ResourceTypeKey resourceKey, final YAMLKeyValue keyValue) {
//         // Get the tree of keys leading up to this one
//         final List<String> keys = new ArrayList<>();
//         YAMLKeyValue currentKey = keyValue;
//         do {
//             keys.add(currentKey.getKeyText());
//         } while ((currentKey = PsiTreeUtil.getParentOfType(currentKey, YAMLKeyValue.class)) != null);
// 
//         // We have iterated from the inside out, so flip this around to get it in the correct direction for the ModelProvider
//         Collections.reverse(keys);
//         return modelProvider.findModel(resourceKey, keys);
//     }
// 
//     /**
//      * Find the corresponding {@link Property} object that relates to the given {@link YAMLKeyValue}.
//      *
//      * @param modelProvider the model provider to use for looking up schema resources.
//      * @param resourceKey the top-level key of the resource.
//      * @param keyValue the {@code YAMLKeyValue} to search back from.
//      * @return the corresponding property or {@code null} if one cannot be located.
//      */
//     @Nullable
//     public static Property propertyForKey(@NotNull final ModelProvider modelProvider, @NotNull final ResourceTypeKey resourceKey, @NotNull final YAMLKeyValue keyValue) {
//         // Get the tree of keys leading up to this one
//         final List<String> keys = new ArrayList<>();
//         YAMLKeyValue currentKey = keyValue;
//         while ((currentKey = PsiTreeUtil.getParentOfType(currentKey, YAMLKeyValue.class)) != null) {
//             keys.add(currentKey.getKeyText());
//         }
// 
//         // We have iterated from the inside out, so flip this around to get it in the correct direction for the ModelProvider
//         Collections.reverse(keys);
//         return modelProvider.findProperties(resourceKey, keys).get(keyValue.getKeyText());
//     }
// }


import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.yaml.psi.YAMLKeyValue;
import org.jetbrains.yaml.psi.YAMLMapping;
import com.github.tinselspoon.intellij.kubernetes.KubernetesYamlPsiUtil;
import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.lang.annotation.Annotator;
import com.intellij.psi.PsiElement;
package com.github.tinselspoon.intellij.kubernetes.codeInsight;




/**
 * Finds {@link YAMLMapping}s with duplicated keys.
 */
public class DuplicateKeyAnnotator implements Annotator {

    @Override
    public void annotate(@NotNull final PsiElement element, @NotNull final AnnotationHolder annotationHolder) {
// Path: src/com/github/tinselspoon/intellij/kubernetes/KubernetesYamlPsiUtil.java
// public final class KubernetesYamlPsiUtil {
// 
//     /** Static class private constructor. */
//     private KubernetesYamlPsiUtil() {
//         // no construction
//     }
// 
//     /**
//      * Find the {@link ResourceTypeKey} for the current document.
//      *
//      * @param element an element within the document to check.
//      * @return the resource type key, or {@code null} if the "apiVersion" and "kind" fields are not present.
//      */
//     @Nullable
//     public static ResourceTypeKey findResourceKey(final PsiElement element) {
//         // Get the top-level mapping
//         final YAMLMapping topLevelMapping = getTopLevelMapping(element);
//         final String apiVersion = getValueText(topLevelMapping, "apiVersion");
//         final String kind = getValueText(topLevelMapping, "kind");
//         if (apiVersion != null && kind != null) {
//             return new ResourceTypeKey(apiVersion, kind);
//         } else {
//             return null;
//         }
//     }
// 
//     /**
//      * Gets the top-level mapping in the document, if present.
//      *
//      * @param element an element within the document.
//      * @return the top-level mapping, or {@code null} if one is not defined (e.g. in an empty document).
//      */
//     @Nullable
//     public static YAMLMapping getTopLevelMapping(final PsiElement element) {
//         final YAMLDocument document = PsiTreeUtil.getParentOfType(element, YAMLDocument.class);
//         if (document != null) {
//             final YAMLValue topLevelValue = document.getTopLevelValue();
//             if (topLevelValue instanceof YAMLMapping) {
//                 return (YAMLMapping) topLevelValue;
//             }
//         }
//         return null;
//     }
// 
//     /**
//      * Gets the text of the value held by the given key within a mapping.
//      *
//      * @param mapping the mapping to search through.
//      * @param key the key to search for.
//      * @return the trimmed text value of the key, or {@code null} if the mapping is null or the key was not found.
//      */
//     @Nullable
//     public static String getValueText(@Nullable final YAMLMapping mapping, @NotNull final String key) {
//         return Optional.ofNullable(mapping).map(m -> m.getKeyValueByKey(key)).map(YAMLKeyValue::getValueText).map(String::trim).orElse(null);
//     }
// 
//     /**
//      * Determines whether the element is within a Kubernetes YAML file. This is done by checking for the presence of "apiVersion" or "kind" as top-level keys within the first document of the file.
//      *
//      * @param element an element within the file to check.
//      * @return true if the element is within A Kubernetes YAML file, otherwise, false.
//      */
//     public static boolean isKubernetesFile(final PsiElement element) {
//         final PsiFile file = element.getContainingFile();
//         if (file instanceof YAMLFile) {
//             final Collection<YAMLKeyValue> keys = YAMLUtil.getTopLevelKeys((YAMLFile) file);
//             return keys.stream().map(YAMLKeyValue::getKeyText).anyMatch(s -> "apiVersion".equals(s) || "kind".equals(s));
//         }
//         return false;
//     }
// 
//     /**
//      * Find the corresponding {@link Model} object that represents the value of a given {@link YAMLKeyValue}.
//      *
//      * @param modelProvider the model provider to use for looking up schema resources.
//      * @param resourceKey the top-level key of the resource.
//      * @param keyValue the {@code YAMLKeyValue} to search back from.
//      * @return the corresponding model or {@code null} if one cannot be located.
//      */
//     @Nullable
//     public static Model modelForKey(final ModelProvider modelProvider, final ResourceTypeKey resourceKey, final YAMLKeyValue keyValue) {
//         // Get the tree of keys leading up to this one
//         final List<String> keys = new ArrayList<>();
//         YAMLKeyValue currentKey = keyValue;
//         do {
//             keys.add(currentKey.getKeyText());
//         } while ((currentKey = PsiTreeUtil.getParentOfType(currentKey, YAMLKeyValue.class)) != null);
// 
//         // We have iterated from the inside out, so flip this around to get it in the correct direction for the ModelProvider
//         Collections.reverse(keys);
//         return modelProvider.findModel(resourceKey, keys);
//     }
// 
//     /**
//      * Find the corresponding {@link Property} object that relates to the given {@link YAMLKeyValue}.
//      *
//      * @param modelProvider the model provider to use for looking up schema resources.
//      * @param resourceKey the top-level key of the resource.
//      * @param keyValue the {@code YAMLKeyValue} to search back from.
//      * @return the corresponding property or {@code null} if one cannot be located.
//      */
//     @Nullable
//     public static Property propertyForKey(@NotNull final ModelProvider modelProvider, @NotNull final ResourceTypeKey resourceKey, @NotNull final YAMLKeyValue keyValue) {
//         // Get the tree of keys leading up to this one
//         final List<String> keys = new ArrayList<>();
//         YAMLKeyValue currentKey = keyValue;
//         while ((currentKey = PsiTreeUtil.getParentOfType(currentKey, YAMLKeyValue.class)) != null) {
//             keys.add(currentKey.getKeyText());
//         }
// 
//         // We have iterated from the inside out, so flip this around to get it in the correct direction for the ModelProvider
//         Collections.reverse(keys);
//         return modelProvider.findProperties(resourceKey, keys).get(keyValue.getKeyText());
//     }
// }


// Path: src/com/github/tinselspoon/intellij/kubernetes/codeInsight/DuplicateKeyAnnotator.java
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.yaml.psi.YAMLKeyValue;
import org.jetbrains.yaml.psi.YAMLMapping;
import com.github.tinselspoon.intellij.kubernetes.KubernetesYamlPsiUtil;
import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.lang.annotation.Annotator;
import com.intellij.psi.PsiElement;

package com.github.tinselspoon.intellij.kubernetes.codeInsight;




/**
 * Finds {@link YAMLMapping}s with duplicated keys.
 */
public class DuplicateKeyAnnotator implements Annotator {

    @Override
    public void annotate(@NotNull final PsiElement element, @NotNull final AnnotationHolder annotationHolder) {
        if (!KubernetesYamlPsiUtil.isKubernetesFile(element)) {