From 098a2ec4b2795047e1e0998d96bd4ad44378ecb5 Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Mon, 23 Jul 2018 15:28:25 +0300 Subject: [PATCH] #581 add pure contract and fix possible NPEs in `getParentMapping` usages --- .../YamlKeyCompletionInsertHandler.java | 1 + .../YAMLDuplicatedKeysInspection.java | 4 ++- .../YamlNonEditableKeysInspectionBase.java | 27 +++++++++++-------- .../org/jetbrains/yaml/psi/YAMLKeyValue.java | 3 ++- 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/plugins/yaml/src/org/jetbrains/yaml/completion/YamlKeyCompletionInsertHandler.java b/plugins/yaml/src/org/jetbrains/yaml/completion/YamlKeyCompletionInsertHandler.java index c9f03d06b854..50d4ec264504 100644 --- a/plugins/yaml/src/org/jetbrains/yaml/completion/YamlKeyCompletionInsertHandler.java +++ b/plugins/yaml/src/org/jetbrains/yaml/completion/YamlKeyCompletionInsertHandler.java @@ -59,6 +59,7 @@ public abstract class YamlKeyCompletionInsertHandler im final YAMLKeyValue keyValue = PsiTreeUtil.getParentOfType(elementAtCaret, YAMLKeyValue.class); assert keyValue != null; + assert keyValue.getParentMapping() != null; context.commitDocument(); if (keyValue.getValue() != null) { diff --git a/plugins/yaml/src/org/jetbrains/yaml/inspections/YAMLDuplicatedKeysInspection.java b/plugins/yaml/src/org/jetbrains/yaml/inspections/YAMLDuplicatedKeysInspection.java index acd66c6a9fc7..d7cdcfb04166 100644 --- a/plugins/yaml/src/org/jetbrains/yaml/inspections/YAMLDuplicatedKeysInspection.java +++ b/plugins/yaml/src/org/jetbrains/yaml/inspections/YAMLDuplicatedKeysInspection.java @@ -41,6 +41,8 @@ public class YAMLDuplicatedKeysInspection extends LocalInspectionTool { if (entry.getValue().size() > 1) { entry.getValue().forEach((duplicatedKey) -> { assert duplicatedKey.getKey() != null; + assert duplicatedKey.getParentMapping() != null : "This key is get from mapping"; + holder.registerProblem(duplicatedKey.getKey(), YAMLBundle.message("YAMLDuplicatedKeysInspection.duplicated.key", entry.getKey()), ProblemHighlightType.GENERIC_ERROR_OR_WARNING, new RemoveDuplicatedKeyQuickFix(duplicatedKey)); @@ -68,7 +70,7 @@ public class YAMLDuplicatedKeysInspection extends LocalInspectionTool { @Override public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { YAMLKeyValue keyVal = myKeyValueHolder.getElement(); - if (keyVal == null) { + if (keyVal == null || keyVal.getParentMapping() == null) { return; } diff --git a/plugins/yaml/src/org/jetbrains/yaml/meta/impl/YamlNonEditableKeysInspectionBase.java b/plugins/yaml/src/org/jetbrains/yaml/meta/impl/YamlNonEditableKeysInspectionBase.java index 9b0287766e4a..fc6c46cf4638 100644 --- a/plugins/yaml/src/org/jetbrains/yaml/meta/impl/YamlNonEditableKeysInspectionBase.java +++ b/plugins/yaml/src/org/jetbrains/yaml/meta/impl/YamlNonEditableKeysInspectionBase.java @@ -7,17 +7,18 @@ import com.intellij.codeInspection.LocalQuickFix; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.codeInspection.ProblemHighlightType; import com.intellij.codeInspection.ProblemsHolder; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; -import com.intellij.psi.PsiRecursiveElementVisitor; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; import org.jetbrains.yaml.YAMLBundle; import org.jetbrains.yaml.psi.YAMLKeyValue; +import org.jetbrains.yaml.psi.YamlRecursivePsiElementVisitor; import java.util.ArrayList; +import java.util.Objects; @ApiStatus.Experimental public abstract class YamlNonEditableKeysInspectionBase extends YamlMetaTypeInspectionBase { @@ -70,22 +71,26 @@ public abstract class YamlNonEditableKeysInspectionBase extends YamlMetaTypeInsp public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { final ArrayList keysToDelete = new ArrayList<>(); - descriptor.getPsiElement().getContainingFile().accept(new PsiRecursiveElementVisitor() { + descriptor.getPsiElement().getContainingFile().accept(new YamlRecursivePsiElementVisitor() { @Override - public void visitElement(PsiElement element) { - if (element instanceof YAMLKeyValue) { - final YamlMetaTypeProvider.MetaTypeProxy meta = myMetaTypeProvider.getKeyValueMetaType((YAMLKeyValue)element); - if (meta != null && !meta.getField().isEditable()) { - keysToDelete.add((YAMLKeyValue)element); - return; + public void visitKeyValue(@NotNull YAMLKeyValue keyValue) { + final YamlMetaTypeProvider.MetaTypeProxy meta = myMetaTypeProvider.getKeyValueMetaType(keyValue); + if (meta != null && !meta.getField().isEditable()) { + if (keyValue.getParentMapping() != null) { + keysToDelete.add(keyValue); } + else { + Logger.getInstance(YamlNonEditableKeysInspectionBase.class) + .warn("Wanted to remove KV, but it does not have a parent mapping"); + } + return; } - super.visitElement(element); + super.visitKeyValue(keyValue); } }); for (YAMLKeyValue keyValue : keysToDelete) { - keyValue.getParentMapping().deleteKeyValue(keyValue); + Objects.requireNonNull(keyValue.getParentMapping()).deleteKeyValue(keyValue); } } } diff --git a/plugins/yaml/src/org/jetbrains/yaml/psi/YAMLKeyValue.java b/plugins/yaml/src/org/jetbrains/yaml/psi/YAMLKeyValue.java index fea071cf60ee..7feb359533f6 100644 --- a/plugins/yaml/src/org/jetbrains/yaml/psi/YAMLKeyValue.java +++ b/plugins/yaml/src/org/jetbrains/yaml/psi/YAMLKeyValue.java @@ -26,7 +26,8 @@ public interface YAMLKeyValue extends YAMLPsiElement, PsiNamedElement, PomTarget @Contract(pure = true) @NotNull String getValueText(); - + + @Contract(pure = true) @Nullable YAMLMapping getParentMapping();