diff --git a/json/src/com/jetbrains/jsonSchema/impl/JsonBySchemaObjectAnnotator.java b/json/src/com/jetbrains/jsonSchema/impl/JsonBySchemaObjectAnnotator.java index a2b0a2c23a3d..40a7a2311c73 100644 --- a/json/src/com/jetbrains/jsonSchema/impl/JsonBySchemaObjectAnnotator.java +++ b/json/src/com/jetbrains/jsonSchema/impl/JsonBySchemaObjectAnnotator.java @@ -65,6 +65,21 @@ public class JsonBySchemaObjectAnnotator implements Annotator { } if (checkIfAlreadyProcessed(holder, firstProp.getDelegate())) return; + final JsonValueAdapter firstPropValue = firstProp.getValue(); + if (firstPropValue != null) checkFirstPropValue(element, holder, walker, firstProp, firstPropValue); + + if (firstProp.getParentObject() != null && walker.isTopJsonElement(firstProp.getParentObject().getDelegate().getParent())) { + checkRootObject(holder, firstProp.getParentObject(), walker); + } + if (firstProp.getParentArray() != null && walker.isTopJsonElement(firstProp.getParentArray().getDelegate().getParent())) { + checkRootObject(holder, firstProp.getParentArray(), walker); + } + } + + private void checkFirstPropValue(@NotNull PsiElement element, + @NotNull AnnotationHolder holder, + JsonLikePsiWalker walker, + JsonPropertyAdapter firstProp, JsonValueAdapter firstPropValue) { final List checkers = new ArrayList<>(); JsonSchemaWalker.findSchemasForAnnotation(firstProp.getDelegate(), JsonSchemaWalker.getWalker(element, myRootSchema), new JsonSchemaWalker.CompletionSchemesConsumer() { @Override @@ -74,7 +89,7 @@ public class JsonBySchemaObjectAnnotator implements Annotator { @NotNull List steps) { final BySchemaChecker checker = new BySchemaChecker(walker); final Set validatedProperties = new HashSet<>(); - checker.checkByScheme(firstProp.getValue(), schema, validatedProperties); + checker.checkByScheme(firstPropValue, schema, validatedProperties); checkers.add(checker); } @@ -85,7 +100,7 @@ public class JsonBySchemaObjectAnnotator implements Annotator { @NotNull List steps) { final BySchemaChecker checker = new BySchemaChecker(walker); final Set validatedProperties = new HashSet<>(); - checker.processOneOf(firstProp.getValue(), list, validatedProperties); + checker.processOneOf(firstPropValue, list, validatedProperties); checkers.add(checker); } @@ -96,7 +111,7 @@ public class JsonBySchemaObjectAnnotator implements Annotator { @NotNull List steps) { final BySchemaChecker checker = new BySchemaChecker(walker); final Set validatedProperties = new HashSet<>(); - checker.processAnyOf(firstProp.getValue(), list, validatedProperties); + checker.processAnyOf(firstPropValue, list, validatedProperties); checkers.add(checker); } }, myRootSchema, mySchemaFile); @@ -118,13 +133,7 @@ public class JsonBySchemaObjectAnnotator implements Annotator { } } - if (processCheckerResults(holder, checker)) return; - if (firstProp.getParentObject() != null && walker.isTopJsonElement(firstProp.getParentObject().getDelegate().getParent())) { - checkRootObject(holder, firstProp.getParentObject(), walker); - } - if (firstProp.getParentArray() != null && walker.isTopJsonElement(firstProp.getParentArray().getDelegate().getParent())) { - checkRootObject(holder, firstProp.getParentArray(), walker); - } + processCheckerResults(holder, checker); } private static JsonValueAdapter findTopLevelElement(@NotNull JsonLikePsiWalker walker, @NotNull PsiElement element) { @@ -160,15 +169,13 @@ public class JsonBySchemaObjectAnnotator implements Annotator { return false; } - private static boolean processCheckerResults(@NotNull AnnotationHolder holder, BySchemaChecker checker) { + private static void processCheckerResults(@NotNull AnnotationHolder holder, BySchemaChecker checker) { if (! checker.isCorrect()) { for (Map.Entry entry : checker.getErrors().entrySet()) { if (checkIfAlreadyProcessed(holder, entry.getKey())) continue; holder.createWarningAnnotation(entry.getKey(), entry.getValue()); } - return true; } - return false; } private static class BySchemaChecker { @@ -604,7 +611,7 @@ public class JsonBySchemaObjectAnnotator implements Annotator { } } - private void processOneOf(JsonValueAdapter value, List oneOf, Set validatedProperties) { + private void processOneOf(@NotNull JsonValueAdapter value, List oneOf, Set validatedProperties) { final Map errors = new HashMap<>(); int cntCorrect = 0; boolean validatedPropertiesAdded = false; @@ -647,7 +654,7 @@ public class JsonBySchemaObjectAnnotator implements Annotator { return !checker.getErrors().containsKey(value); } - private void processAnyOf(JsonValueAdapter value, List anyOf, Set validatedProperties) { + private void processAnyOf(@NotNull JsonValueAdapter value, List anyOf, Set validatedProperties) { final Map errors = new HashMap<>(); for (JsonSchemaObject object : anyOf) { final BySchemaChecker checker = new BySchemaChecker(myWalker); diff --git a/json/tests/test/com/jetbrains/jsonSchema/JsonSchemaHighlightingTest.java b/json/tests/test/com/jetbrains/jsonSchema/JsonSchemaHighlightingTest.java index 8ee3b0b78fb7..14c404cb2d5f 100644 --- a/json/tests/test/com/jetbrains/jsonSchema/JsonSchemaHighlightingTest.java +++ b/json/tests/test/com/jetbrains/jsonSchema/JsonSchemaHighlightingTest.java @@ -328,6 +328,12 @@ public class JsonSchemaHighlightingTest extends DaemonAnalyzerTestCase { testImpl(schemaText, inputText); } + public void testOneOfWithEmptyPropertyValue() throws Exception { + String schemaText = FileUtil.loadFile(new File(getTestDataPath() + "/oneOfSchema.json")); + String inputText = FileUtil.loadFile(new File(getTestDataPath() + "/oneOfWithEmptyPropertyValue.json")); + testImpl(schemaText, inputText); + } + public void testCycledSchema() throws Exception { String schemaText = FileUtil.loadFile(new File(getTestDataPath() + "/cycledSchema.json")); String inputText = FileUtil.loadFile(new File(getTestDataPath() + "/testCycledSchema.json")); diff --git a/json/tests/test/com/jetbrains/jsonSchema/impl/JsonBySchemaHeavyCompletionTest.java b/json/tests/test/com/jetbrains/jsonSchema/impl/JsonBySchemaHeavyCompletionTest.java index 9531abab953f..3eb06b2ef9cf 100644 --- a/json/tests/test/com/jetbrains/jsonSchema/impl/JsonBySchemaHeavyCompletionTest.java +++ b/json/tests/test/com/jetbrains/jsonSchema/impl/JsonBySchemaHeavyCompletionTest.java @@ -19,6 +19,7 @@ import com.intellij.codeInsight.completion.CodeCompletionHandlerBase; import com.intellij.codeInsight.completion.CompletionType; import com.jetbrains.jsonSchema.JsonSchemaHeavyAbstractTest; import com.jetbrains.jsonSchema.JsonSchemaMappingsConfigurationBase; +import org.jetbrains.annotations.NotNull; import java.util.Collections; @@ -85,7 +86,35 @@ public class JsonBySchemaHeavyCompletionTest extends JsonSchemaHeavyAbstractTest baseInsertTest("insertPropertyName", "testNameWithDefaultStringValueComma"); } - private void baseInsertTest(final String folder, final String testFile) throws Exception { + public void testOneOfWithNotFilledPropertyValue() throws Exception { + baseCompletionTest("oneOfWithEnumValue", "oneOfWithEmptyPropertyValue", "\"business\"", "\"home\""); + } + + private void baseCompletionTest(@SuppressWarnings("SameParameterValue") final String folder, + @SuppressWarnings("SameParameterValue") final String testFile, @NotNull String... items) throws Exception { + baseTest(folder, testFile, () -> { + complete(); + assertStringItems(items); + }); + } + + private void baseInsertTest(@SuppressWarnings("SameParameterValue") final String folder, final String testFile) throws Exception { + baseTest(folder, testFile, () -> { + final CodeCompletionHandlerBase handlerBase = new CodeCompletionHandlerBase(CompletionType.BASIC); + handlerBase.invokeCompletion(getProject(), getEditor()); + if (myItems != null) { + selectItem(myItems[0]); + } + try { + checkResultByFile("/" + folder + "/" + testFile + "_after.json"); + } + catch (Exception e) { + throw new RuntimeException(e); + } + }); + } + + private void baseTest(@NotNull final String folder, @NotNull final String testFile, @NotNull final Runnable checker) throws Exception { skeleton(new Callback() { @Override public void registerSchemes() { @@ -105,17 +134,7 @@ public class JsonBySchemaHeavyCompletionTest extends JsonSchemaHeavyAbstractTest @Override public void doCheck() { - final CodeCompletionHandlerBase handlerBase = new CodeCompletionHandlerBase(CompletionType.BASIC); - handlerBase.invokeCompletion(getProject(), getEditor()); - if (myItems != null) { - selectItem(myItems[0]); - } - try { - checkResultByFile("/" + folder + "/" + testFile + "_after.json"); - } - catch (Exception e) { - throw new RuntimeException(e); - } + checker.run(); } }); } diff --git a/json/tests/testData/jsonSchema/completion/oneOfWithEnumValue/Schema.json b/json/tests/testData/jsonSchema/completion/oneOfWithEnumValue/Schema.json new file mode 100644 index 000000000000..c1aae4d32d35 --- /dev/null +++ b/json/tests/testData/jsonSchema/completion/oneOfWithEnumValue/Schema.json @@ -0,0 +1,55 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + + "definitions": { + "address": { + "type": "object", + "properties": { + "street_address": { "type": "string" }, + "city": { "type": "string" }, + "state": { "type": "string" } + }, + "required": ["street_address", "city", "state"] + }, + "office_address": { + "properties": { + "type": { "enum": [ "business" ] }, + "building": { "type": "string" } + }, + "required": ["type", "building"], + "additionalProperties": false + }, + "home_address": { + "properties": { + "type": { "enum": [ "home" ] }, + "street_address": { "type": "string" }, + "city": { "type": "string" }, + "state": { "type": "string" } + }, + "required": ["type", "street_address", "city", "state"], + "additionalProperties": false + }, + "partOne": { + "properties": {"one": {"type": "string"}} + }, + "partTwo": { + "properties": {"two": {"type": "integer"}} + } + }, + "type": "object", + "properties": { + "client_address": { + "oneOf": [ + { "$ref": "#/definitions/office_address" }, + { "$ref": "#/definitions/home_address" } + ] + }, + "parts": { + "oneOf": [ + { "$ref": "#/definitions/partOne" }, + { "$ref": "#/definitions/partTwo" } + ], + "additionalProperties": false + } + } +} \ No newline at end of file diff --git a/json/tests/testData/jsonSchema/completion/oneOfWithEnumValue/oneOfWithEmptyPropertyValue.json b/json/tests/testData/jsonSchema/completion/oneOfWithEnumValue/oneOfWithEmptyPropertyValue.json new file mode 100644 index 000000000000..9f582f6c4830 --- /dev/null +++ b/json/tests/testData/jsonSchema/completion/oneOfWithEnumValue/oneOfWithEmptyPropertyValue.json @@ -0,0 +1,6 @@ +{ + "client_address": { + "building": "1", + "type": + } +} \ No newline at end of file diff --git a/json/tests/testData/jsonSchema/highlighting/oneOfWithEmptyPropertyValue.json b/json/tests/testData/jsonSchema/highlighting/oneOfWithEmptyPropertyValue.json new file mode 100644 index 000000000000..fc792c6daead --- /dev/null +++ b/json/tests/testData/jsonSchema/highlighting/oneOfWithEmptyPropertyValue.json @@ -0,0 +1,6 @@ +{ + "client_address": { + "building": "1", + "type": + } +} \ No newline at end of file