mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
RUBY-23497: yaml by json schema - support empty file, empty object and adjust quick fixes
This commit is contained in:
@@ -53,6 +53,8 @@ public interface JsonLikePsiWalker {
|
||||
return element.getTextRange();
|
||||
}
|
||||
|
||||
default boolean acceptsEmptyRoot() { return false; }
|
||||
|
||||
@Nullable
|
||||
static JsonLikePsiWalker getWalker(@NotNull final PsiElement element, JsonSchemaObject schemaObject) {
|
||||
if (JSON_ORIGINAL_PSI_WALKER.handles(element)) return JSON_ORIGINAL_PSI_WALKER;
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
package com.jetbrains.jsonSchema.extension;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.impl.source.tree.LeafPsiElement;
|
||||
import com.jetbrains.jsonSchema.impl.JsonSchemaType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -9,8 +11,11 @@ public interface JsonLikeSyntaxAdapter {
|
||||
@Nullable PsiElement getPropertyValue(PsiElement property);
|
||||
@NotNull default PsiElement adjustValue(@NotNull PsiElement value) { return value; }
|
||||
@Nullable String getPropertyName(PsiElement property);
|
||||
@NotNull PsiElement createProperty(@NotNull final String name, @NotNull final String value);
|
||||
boolean ensureComma(PsiElement backward, PsiElement self, PsiElement newElement);
|
||||
@NotNull PsiElement createProperty(@NotNull final String name, @NotNull final String value, PsiElement element);
|
||||
boolean ensureComma(PsiElement self, PsiElement newElement);
|
||||
void removeIfComma(PsiElement forward);
|
||||
boolean fixWhitespaceBefore(PsiElement initialElement, PsiElement element);
|
||||
@NotNull String getDefaultValueFromType(@Nullable JsonSchemaType type);
|
||||
PsiElement adjustNewProperty(PsiElement element);
|
||||
PsiElement adjustPropertyAnchor(LeafPsiElement element);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.impl.source.tree.LeafPsiElement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.ThreeState;
|
||||
import com.jetbrains.jsonSchema.extension.JsonLikePsiWalker;
|
||||
import com.jetbrains.jsonSchema.extension.JsonLikeSyntaxAdapter;
|
||||
@@ -193,14 +194,14 @@ public class JsonOriginalPsiWalker implements JsonLikePsiWalker {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement createProperty(@NotNull String name, @NotNull String value) {
|
||||
public PsiElement createProperty(@NotNull String name, @NotNull String value, PsiElement element) {
|
||||
return myGenerator.createProperty(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean ensureComma(PsiElement backward, PsiElement self, PsiElement newElement) {
|
||||
if (backward instanceof JsonProperty) {
|
||||
self.addAfter(myGenerator.createComma(), backward);
|
||||
public boolean ensureComma(PsiElement self, PsiElement newElement) {
|
||||
if (newElement instanceof JsonProperty && self instanceof JsonProperty) {
|
||||
self.getParent().addAfter(myGenerator.createComma(), self);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -217,6 +218,22 @@ public class JsonOriginalPsiWalker implements JsonLikePsiWalker {
|
||||
public boolean fixWhitespaceBefore(PsiElement initialElement, PsiElement element) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getDefaultValueFromType(@Nullable JsonSchemaType type) {
|
||||
return type == null ? "" : type.getDefaultValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement adjustNewProperty(PsiElement element) {
|
||||
return element;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement adjustPropertyAnchor(LeafPsiElement element) {
|
||||
throw new IncorrectOperationException("Shouldn't use leafs for insertion in pure JSON!");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -300,7 +300,7 @@ class JsonSchemaAnnotatorChecker {
|
||||
if (object.shouldCheckIntegralRequirements()) {
|
||||
final Set<String> required = schema.getRequired();
|
||||
if (required != null) {
|
||||
HashSet<String> requiredNames = ContainerUtil.newHashSet(required);
|
||||
HashSet<String> requiredNames = ContainerUtil.newLinkedHashSet(required);
|
||||
requiredNames.removeAll(set);
|
||||
if (!requiredNames.isEmpty()) {
|
||||
JsonValidationError.MissingMultiplePropsIssueData data = createMissingPropertiesData(schema, requiredNames);
|
||||
|
||||
@@ -131,7 +131,7 @@ public class JsonSchemaComplianceChecker {
|
||||
myHolder.registerProblem(psiElement, range, value);
|
||||
}
|
||||
else {
|
||||
myHolder.registerProblem(psiElement, range, value, fix);
|
||||
myHolder.registerProblem(range.isEmpty() ? psiElement.getContainingFile() : psiElement, range, value, fix);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ public class JsonSchemaComplianceChecker {
|
||||
if (!isTop) ref.set(el);
|
||||
return isTop;
|
||||
});
|
||||
return ref.isNull() ? null : walker.createValueAdapter(ref.get());
|
||||
return ref.isNull() ? (walker.acceptsEmptyRoot() ? walker.createValueAdapter(element) : null) : walker.createValueAdapter(ref.get());
|
||||
}
|
||||
|
||||
private boolean checkIfAlreadyProcessed(@NotNull PsiElement property) {
|
||||
|
||||
@@ -408,9 +408,9 @@ public class JsonSchemaReader {
|
||||
private static MyReader createRequired() {
|
||||
return (element, object, queue) -> {
|
||||
if (element instanceof JsonArray) {
|
||||
object.setRequired(((JsonArray)element).getValueList().stream()
|
||||
object.setRequired(ContainerUtil.newLinkedHashSet(((JsonArray)element).getValueList().stream()
|
||||
.filter(notEmptyString())
|
||||
.map(el -> StringUtil.unquoteString(el.getText())).collect(Collectors.toSet()));
|
||||
.map(el -> StringUtil.unquoteString(el.getText())).collect(Collectors.toList())));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -19,12 +19,14 @@ import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.impl.source.tree.LeafPsiElement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.DocumentUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.jetbrains.jsonSchema.extension.JsonLikeSyntaxAdapter;
|
||||
import com.jetbrains.jsonSchema.impl.JsonSchemaType;
|
||||
import com.jetbrains.jsonSchema.impl.JsonValidationError;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -60,12 +62,13 @@ public class AddMissingPropertyFix implements LocalQuickFix, BatchQuickFix<Commo
|
||||
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
|
||||
PsiElement element = descriptor.getPsiElement();
|
||||
Ref<Boolean> hadComma = Ref.create(false);
|
||||
VirtualFile file = element.getContainingFile().getVirtualFile();
|
||||
PsiElement newElement = performFix(element, hadComma);
|
||||
// if we have more than one property, don't expand templates and don't move the caret
|
||||
if (newElement == null) return;
|
||||
|
||||
PsiElement value = myQuickFixAdapter.getPropertyValue(newElement);
|
||||
FileEditor fileEditor = FileEditorManager.getInstance(project).getSelectedEditor(element.getContainingFile().getVirtualFile());
|
||||
FileEditor fileEditor = FileEditorManager.getInstance(project).getSelectedEditor(file);
|
||||
EditorEx editor = EditorUtil.getEditorEx(fileEditor);
|
||||
assert editor != null;
|
||||
if (value == null) {
|
||||
@@ -83,7 +86,12 @@ public class AddMissingPropertyFix implements LocalQuickFix, BatchQuickFix<Commo
|
||||
? new MacroCallNode(new CompleteMacro())
|
||||
: isEmptyArray ? new EmptyNode() : new ConstantNode(goInside ? StringUtil.unquoteString(text) : text));
|
||||
editor.getCaretModel().moveToOffset(newElement.getTextRange().getStartOffset());
|
||||
builder.setEndVariableAfter(newElement);
|
||||
if (PsiTreeUtil.nextLeaf(newElement) != null) {
|
||||
builder.setEndVariableAfter(newElement);
|
||||
}
|
||||
else {
|
||||
builder.setEndVariableBefore(newElement.getLastChild());
|
||||
}
|
||||
WriteAction.run(() -> {
|
||||
Template template = builder.buildInlineTemplate();
|
||||
template.setToReformat(true);
|
||||
@@ -92,23 +100,43 @@ public class AddMissingPropertyFix implements LocalQuickFix, BatchQuickFix<Commo
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiElement performFix(@Nullable PsiElement element, @NotNull Ref<Boolean> hadComma) {
|
||||
if (element == null) return null;
|
||||
public PsiElement performFix(@Nullable PsiElement node, @NotNull Ref<Boolean> hadComma) {
|
||||
if (node == null) return null;
|
||||
PsiElement element = node instanceof PsiFile ? node.getFirstChild() : node;
|
||||
Ref<PsiElement> newElementRef = Ref.create(null);
|
||||
|
||||
WriteAction.run(() -> {
|
||||
boolean isSingle = myData.myMissingPropertyIssues.size() == 1;
|
||||
for (JsonValidationError.MissingPropertyIssueData issue: myData.myMissingPropertyIssues) {
|
||||
PsiElement processedElement = element;
|
||||
List<JsonValidationError.MissingPropertyIssueData> reverseOrder
|
||||
= ContainerUtil.reverse(ContainerUtil.newArrayList(myData.myMissingPropertyIssues));
|
||||
for (JsonValidationError.MissingPropertyIssueData issue: reverseOrder) {
|
||||
Object defaultValueObject = issue.defaultValue;
|
||||
String defaultValue = defaultValueObject instanceof String ? StringUtil.wrapWithDoubleQuote(defaultValueObject.toString()) : null;
|
||||
PsiElement newElement = element
|
||||
.addBefore(
|
||||
myQuickFixAdapter.createProperty(issue.propertyName, defaultValue == null ? getDefaultValueFromType(issue) : defaultValue),
|
||||
element.getLastChild());
|
||||
PsiElement backward = PsiTreeUtil.skipWhitespacesBackward(newElement);
|
||||
hadComma.set(myQuickFixAdapter.ensureComma(backward, element, newElement));
|
||||
PsiElement property = myQuickFixAdapter.createProperty(issue.propertyName, defaultValue == null
|
||||
? myQuickFixAdapter
|
||||
.getDefaultValueFromType(issue.propertyType)
|
||||
: defaultValue, element);
|
||||
PsiElement newElement;
|
||||
if (processedElement instanceof LeafPsiElement) {
|
||||
newElement = myQuickFixAdapter.adjustPropertyAnchor((LeafPsiElement)processedElement).addBefore(property, null);
|
||||
}
|
||||
else {
|
||||
if (processedElement == element) {
|
||||
newElement = processedElement.addBefore(property, processedElement.getLastChild());
|
||||
}
|
||||
else {
|
||||
newElement = processedElement.getParent().addBefore(property, processedElement);
|
||||
}
|
||||
}
|
||||
PsiElement adjusted = myQuickFixAdapter.adjustNewProperty(newElement);
|
||||
hadComma.set(myQuickFixAdapter.ensureComma(adjusted, PsiTreeUtil.skipWhitespacesForward(newElement)));
|
||||
if (!hadComma.get()) {
|
||||
hadComma.set(processedElement == element && myQuickFixAdapter.ensureComma(PsiTreeUtil.skipWhitespacesBackward(newElement), adjusted));
|
||||
}
|
||||
processedElement = adjusted;
|
||||
if (isSingle) {
|
||||
newElementRef.set(newElement);
|
||||
newElementRef.set(adjusted);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -116,12 +144,6 @@ public class AddMissingPropertyFix implements LocalQuickFix, BatchQuickFix<Commo
|
||||
return newElementRef.get();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String getDefaultValueFromType(JsonValidationError.MissingPropertyIssueData issue) {
|
||||
JsonSchemaType propertyType = issue.propertyType;
|
||||
return propertyType == null ? "" : propertyType.getDefaultValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startInWriteAction() {
|
||||
return false;
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.yaml.schema;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.jetbrains.jsonSchema.extension.adapters.JsonArrayValueAdapter;
|
||||
import com.jetbrains.jsonSchema.extension.adapters.JsonObjectValueAdapter;
|
||||
import com.jetbrains.jsonSchema.extension.adapters.JsonPropertyAdapter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class YamlEmptyObjectAdapter implements JsonObjectValueAdapter {
|
||||
private final PsiElement myElement;
|
||||
|
||||
public YamlEmptyObjectAdapter(PsiElement element) {
|
||||
myElement = element;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isObject() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isArray() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStringLiteral() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNumberLiteral() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBooleanLiteral() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<JsonPropertyAdapter> getPropertyList() {
|
||||
return ContainerUtil.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNull() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement getDelegate() {
|
||||
return myElement;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public JsonObjectValueAdapter getAsObject() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public JsonArrayValueAdapter getAsArray() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -12,11 +12,13 @@ import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.impl.source.tree.LeafPsiElement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.util.ThreeState;
|
||||
import com.jetbrains.jsonSchema.extension.JsonLikePsiWalker;
|
||||
import com.jetbrains.jsonSchema.extension.JsonLikeSyntaxAdapter;
|
||||
import com.jetbrains.jsonSchema.extension.adapters.JsonPropertyAdapter;
|
||||
import com.jetbrains.jsonSchema.extension.adapters.JsonValueAdapter;
|
||||
import com.jetbrains.jsonSchema.impl.JsonSchemaType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.yaml.YAMLElementGenerator;
|
||||
@@ -67,6 +69,11 @@ public class YamlJsonPsiWalker implements JsonLikePsiWalker {
|
||||
return element instanceof YAMLFile || element instanceof YAMLDocument;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptsEmptyRoot() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement findElementToCheck(@NotNull PsiElement element) {
|
||||
PsiElement current = element;
|
||||
@@ -87,7 +94,8 @@ public class YamlJsonPsiWalker implements JsonLikePsiWalker {
|
||||
@Nullable
|
||||
@Override
|
||||
public JsonValueAdapter createValueAdapter(@NotNull PsiElement element) {
|
||||
return element instanceof YAMLValue ? YamlPropertyAdapter.createValueAdapterByType((YAMLValue)element) : null;
|
||||
return element instanceof YAMLValue ? YamlPropertyAdapter.createValueAdapterByType((YAMLValue)element)
|
||||
: (element instanceof YAMLDocument ? new YamlEmptyObjectAdapter(element) : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -229,7 +237,7 @@ public class YamlJsonPsiWalker implements JsonLikePsiWalker {
|
||||
assert property instanceof YAMLKeyValue;
|
||||
YAMLValue value = ((YAMLKeyValue)property).getValue();
|
||||
if (value == null) return null;
|
||||
return adjustValue(property);
|
||||
return adjustValue(value);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -249,16 +257,30 @@ public class YamlJsonPsiWalker implements JsonLikePsiWalker {
|
||||
return ((YAMLKeyValue)property).getName();
|
||||
}
|
||||
|
||||
private YAMLKeyValue findPrecedingKeyValueWithNoValue(PsiElement element) {
|
||||
if (PsiUtilCore.getElementType(element) == YAMLTokenTypes.INDENT) {
|
||||
PsiElement prev = element.getPrevSibling();
|
||||
prev = prev == null ? null : prev.getPrevSibling();
|
||||
if (prev instanceof YAMLKeyValue && ((YAMLKeyValue)prev).getValue() == null) {
|
||||
return (YAMLKeyValue)prev;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement createProperty(@NotNull String name, @NotNull String value) {
|
||||
return myGenerator.createYamlKeyValue(name, StringUtil.unquoteString(value));
|
||||
public PsiElement createProperty(@NotNull String name, @NotNull String value, PsiElement element) {
|
||||
YAMLKeyValue keyValue = myGenerator.createYamlKeyValue(name, StringUtil.unquoteString(value));
|
||||
return element instanceof YAMLDocument || findPrecedingKeyValueWithNoValue(element) != null
|
||||
? myGenerator.createDummyYamlWithText(keyValue.getText()).getDocuments().get(0).getFirstChild()
|
||||
: keyValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean ensureComma(PsiElement backward, PsiElement self, PsiElement newElement) {
|
||||
if (newElement instanceof YAMLKeyValue) {
|
||||
newElement.getParent().addAfter(myGenerator.createEol(), newElement);
|
||||
public boolean ensureComma(PsiElement self, PsiElement newElement) {
|
||||
if (newElement instanceof YAMLKeyValue && self instanceof YAMLKeyValue) {
|
||||
self.getParent().addAfter(myGenerator.createEol(), self);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -279,6 +301,33 @@ public class YamlJsonPsiWalker implements JsonLikePsiWalker {
|
||||
public boolean fixWhitespaceBefore(PsiElement initialElement, PsiElement element) {
|
||||
return initialElement instanceof YAMLValue && initialElement != element;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getDefaultValueFromType(@Nullable JsonSchemaType type) {
|
||||
if (type == null) return "";
|
||||
if (type == JsonSchemaType._object) return " ";
|
||||
if (type == JsonSchemaType._array) return " - ";
|
||||
return type.getDefaultValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement adjustNewProperty(PsiElement element) {
|
||||
if (element instanceof YAMLMapping) return element.getFirstChild();
|
||||
return element;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement adjustPropertyAnchor(LeafPsiElement element) {
|
||||
YAMLKeyValue keyValue = findPrecedingKeyValueWithNoValue(element);
|
||||
assert keyValue != null: "Should come here only for YAMLKeyValue with no value and a following indent";
|
||||
keyValue.addBefore(myGenerator.createEol(), null);
|
||||
keyValue.addBefore(myGenerator.createIndent(element.getTextLength()), null);
|
||||
PsiElement prev = element.getPrevSibling();
|
||||
if (prev != null) prev.delete();
|
||||
element.delete();
|
||||
return keyValue;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+4
-3
@@ -21,6 +21,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.yaml.YAMLBundle;
|
||||
import org.jetbrains.yaml.psi.YAMLDocument;
|
||||
import org.jetbrains.yaml.psi.YAMLFile;
|
||||
import org.jetbrains.yaml.psi.YAMLValue;
|
||||
import org.jetbrains.yaml.psi.YamlPsiElementVisitor;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -54,9 +55,9 @@ public class YamlJsonSchemaHighlightingInspection extends LocalInspectionTool {
|
||||
List<YAMLDocument> documents = ((YAMLFile)file).getDocuments();
|
||||
if (documents.size() != 1) return PsiElementVisitor.EMPTY_VISITOR;
|
||||
|
||||
PsiElement root = documents.get(0).getTopLevelValue();
|
||||
if (root == null) return PsiElementVisitor.EMPTY_VISITOR;
|
||||
|
||||
YAMLDocument document = documents.get(0);
|
||||
YAMLValue topLevelValue = document.getTopLevelValue();
|
||||
PsiElement root = topLevelValue == null ? document : topLevelValue;
|
||||
JsonSchemaService service = JsonSchemaService.Impl.get(file.getProject());
|
||||
VirtualFile virtualFile = file.getViewProvider().getVirtualFile();
|
||||
if (!service.isApplicableToFile(virtualFile)) return PsiElementVisitor.EMPTY_VISITOR;
|
||||
|
||||
@@ -4,6 +4,7 @@ package org.jetbrains.yaml.schema;
|
||||
import com.intellij.openapi.util.RecursionManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.TokenType;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.jetbrains.jsonSchema.extension.adapters.JsonObjectValueAdapter;
|
||||
@@ -11,6 +12,7 @@ import com.jetbrains.jsonSchema.extension.adapters.JsonPropertyAdapter;
|
||||
import com.jetbrains.jsonSchema.extension.adapters.JsonValueAdapter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.yaml.YAMLTokenTypes;
|
||||
import org.jetbrains.yaml.psi.*;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -71,6 +73,16 @@ public class YamlPropertyAdapter implements JsonPropertyAdapter {
|
||||
|
||||
@Nullable
|
||||
public static JsonValueAdapter createEmptyValueAdapter(@NotNull PsiElement context, boolean pinSelf) {
|
||||
if (context instanceof YAMLKeyValue && ((YAMLKeyValue)context).getValue() == null) {
|
||||
PsiElement next = PsiTreeUtil.skipWhitespacesForward(context);
|
||||
if (PsiUtilCore.getElementType(next) == YAMLTokenTypes.EOL) {
|
||||
next = PsiTreeUtil.skipWhitespacesForward(next);
|
||||
if (PsiUtilCore.getElementType(next) == YAMLTokenTypes.INDENT && !(PsiTreeUtil.skipWhitespacesForward(next) instanceof YAMLKeyValue)) {
|
||||
// potentially empty object after newline+indent
|
||||
return new YamlEmptyObjectAdapter(next);
|
||||
}
|
||||
}
|
||||
}
|
||||
PsiElement nextSibling = context.getNextSibling();
|
||||
PsiElement nodeToHighlight = PsiUtilCore.getElementType(nextSibling) == TokenType.WHITE_SPACE
|
||||
? nextSibling
|
||||
|
||||
@@ -844,4 +844,45 @@ public class YamlByJsonSchemaHighlightingTest extends JsonSchemaHighlightingTest
|
||||
" <warning descr=\"Schema validation: Type is not allowed. Expected: string.\">-</warning>\n" +
|
||||
" - a");
|
||||
}
|
||||
|
||||
public void testEmptyFile() throws Exception {
|
||||
doTest("{\n" +
|
||||
" \"type\": \"object\",\n" +
|
||||
"\n" +
|
||||
" \"properties\": {\n" +
|
||||
" \"versionAsStringArray\": {\n" +
|
||||
" \"type\": \"array\"\n" +
|
||||
" }\n" +
|
||||
" },\n" +
|
||||
" \"required\": [\"versionAsStringArray\"]\n" +
|
||||
"}", "<warning descr=\"Schema validation: Missing required property 'versionAsStringArray'\"></warning>");
|
||||
}
|
||||
|
||||
public void testEmptyValueBetweenProps() throws Exception {
|
||||
doTest("{\n" +
|
||||
" \"type\": \"object\",\n" +
|
||||
"\n" +
|
||||
" \"properties\": {\n" +
|
||||
" \"versionAsStringArray\": {\n" +
|
||||
" \"type\": \"object\",\n" +
|
||||
" \"properties\": {\n" +
|
||||
" \"xxx\": {\n" +
|
||||
" \"type\": \"number\"\n" +
|
||||
" },\n" +
|
||||
" \"yyy\": {\n" +
|
||||
" \"type\": \"string\"\n" +
|
||||
" },\n" +
|
||||
" \"zzz\": {\n" +
|
||||
" \"type\": \"number\"\n" +
|
||||
" }\n" +
|
||||
" },\n" +
|
||||
" \"required\": [\"xxx\", \"yyy\", \"zzz\"]\n" +
|
||||
" }\n" +
|
||||
" },\n" +
|
||||
" \"required\": [\"versionAsStringArray\"]\n" +
|
||||
"}", "versionAsStringArray:\n" +
|
||||
" zzz: 0\n" +
|
||||
" yyy:<warning descr=\"Schema validation: Type is not allowed. Expected: string.\"> </warning>\n" +
|
||||
" xxx: 0");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,4 +48,69 @@ public class YamlByJsonSchemaQuickFixTest extends JsonSchemaQuickFixTestBase {
|
||||
"}", "a: 5\n<warning>b: 6</warning>\nc: 7", "Remove prohibited property 'b'", "a: 5\n" +
|
||||
"c: 7");
|
||||
}
|
||||
|
||||
public void testEmptyFile() throws Exception {
|
||||
doTest("{\n" +
|
||||
" \"type\": \"object\",\n" +
|
||||
"\n" +
|
||||
" \"properties\": {\n" +
|
||||
" \"versionAsStringArray\": {\n" +
|
||||
" \"type\": \"array\"\n" +
|
||||
" }\n" +
|
||||
" },\n" +
|
||||
" \"required\": [\"versionAsStringArray\"]\n" +
|
||||
"}", "<warning></warning>", "Add missing property 'versionAsStringArray'", "versionAsStringArray:\n" +
|
||||
" - ");
|
||||
}
|
||||
|
||||
public void testEmptyObject() throws Exception {
|
||||
doTest("{\n" +
|
||||
" \"type\": \"object\",\n" +
|
||||
"\n" +
|
||||
" \"properties\": {\n" +
|
||||
" \"versionAsStringArray\": {\n" +
|
||||
" \"type\": \"object\",\n" +
|
||||
" \"properties\": {\n" +
|
||||
" \"xxx\": {\n" +
|
||||
" \"type\": \"array\"\n" +
|
||||
" }\n" +
|
||||
" },\n" +
|
||||
" \"required\": [\"xxx\"]\n" +
|
||||
" }\n" +
|
||||
" },\n" +
|
||||
" \"required\": [\"versionAsStringArray\"]\n" +
|
||||
"}", "versionAsStringArray:\n" +
|
||||
"<warning> </warning>", "Add missing property 'xxx'", "versionAsStringArray:\n" +
|
||||
" xxx:\n" +
|
||||
" - ");
|
||||
}
|
||||
|
||||
public void testEmptyObjectMultipleProps() throws Exception {
|
||||
doTest("{\n" +
|
||||
" \"type\": \"object\",\n" +
|
||||
"\n" +
|
||||
" \"properties\": {\n" +
|
||||
" \"versionAsStringArray\": {\n" +
|
||||
" \"type\": \"object\",\n" +
|
||||
" \"properties\": {\n" +
|
||||
" \"xxx\": {\n" +
|
||||
" \"type\": \"number\"\n" +
|
||||
" },\n" +
|
||||
" \"yyy\": {\n" +
|
||||
" \"type\": \"string\"\n" +
|
||||
" },\n" +
|
||||
" \"zzz\": {\n" +
|
||||
" \"type\": \"number\"\n" +
|
||||
" }\n" +
|
||||
" },\n" +
|
||||
" \"required\": [\"xxx\", \"yyy\", \"zzz\"]\n" +
|
||||
" }\n" +
|
||||
" },\n" +
|
||||
" \"required\": [\"versionAsStringArray\"]\n" +
|
||||
"}", "versionAsStringArray:\n" +
|
||||
"<warning> </warning>","Add missing properties 'xxx', 'yyy', 'zzz'", "versionAsStringArray:\n" +
|
||||
" xxx: 0\n" +
|
||||
" yyy:\n" +
|
||||
" zzz: 0");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user