mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
WEB-34888 Validation of 'allOf' condition is too weak
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
package com.jetbrains.jsonSchema.impl;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.intellij.json.psi.JsonContainer;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
@@ -107,6 +108,12 @@ public class JsonSchemaObject {
|
||||
@Nullable private JsonSchemaObject myElse;
|
||||
private boolean myShouldValidateAgainstJSType;
|
||||
|
||||
public boolean isValidByExclusion() {
|
||||
return myIsValidByExclusion;
|
||||
}
|
||||
|
||||
private boolean myIsValidByExclusion = true;
|
||||
|
||||
public JsonSchemaObject(@NotNull JsonContainer object) {
|
||||
myJsonObject = object;
|
||||
myProperties = new HashMap<>();
|
||||
@@ -117,6 +124,89 @@ public class JsonSchemaObject {
|
||||
myProperties = new HashMap<>();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static JsonSchemaType getSubtypeOfBoth(@NotNull JsonSchemaType selfType,
|
||||
@NotNull JsonSchemaType otherType) {
|
||||
if (otherType == JsonSchemaType._any) return selfType;
|
||||
if (selfType == JsonSchemaType._any) return otherType;
|
||||
//noinspection EnumSwitchStatementWhichMissesCases
|
||||
switch (selfType) {
|
||||
case _string:
|
||||
return otherType == JsonSchemaType._string || otherType == JsonSchemaType._string_number ? JsonSchemaType._string : null;
|
||||
case _number:
|
||||
if (otherType == JsonSchemaType._integer) return JsonSchemaType._integer;
|
||||
return otherType == JsonSchemaType._number || otherType == JsonSchemaType._string_number ? JsonSchemaType._number : null;
|
||||
case _integer:
|
||||
return otherType == JsonSchemaType._number
|
||||
|| otherType == JsonSchemaType._string_number
|
||||
|| otherType == JsonSchemaType._integer ? JsonSchemaType._integer : null;
|
||||
case _object:
|
||||
return otherType == JsonSchemaType._object ? JsonSchemaType._object : null;
|
||||
case _array:
|
||||
return otherType == JsonSchemaType._array ? JsonSchemaType._array : null;
|
||||
case _boolean:
|
||||
return otherType == JsonSchemaType._boolean ? JsonSchemaType._boolean : null;
|
||||
case _null:
|
||||
return otherType == JsonSchemaType._null ? JsonSchemaType._null : null;
|
||||
case _string_number:
|
||||
return otherType == JsonSchemaType._integer
|
||||
|| otherType == JsonSchemaType._number
|
||||
|| otherType == JsonSchemaType._string
|
||||
|| otherType == JsonSchemaType._string_number ? otherType : null;
|
||||
}
|
||||
return otherType;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private JsonSchemaType mergeTypes(@Nullable JsonSchemaType selfType,
|
||||
@Nullable JsonSchemaType otherType,
|
||||
@Nullable Set<JsonSchemaType> otherTypeVariants) {
|
||||
if (selfType == null) return otherType;
|
||||
if (otherType == null) {
|
||||
if (otherTypeVariants != null && !otherTypeVariants.isEmpty()) {
|
||||
Set<JsonSchemaType> filteredVariants = ContainerUtil.newHashSet(otherTypeVariants.size());
|
||||
for (JsonSchemaType variant : otherTypeVariants) {
|
||||
JsonSchemaType subtype = getSubtypeOfBoth(selfType, variant);
|
||||
if (subtype != null) filteredVariants.add(subtype);
|
||||
}
|
||||
if (filteredVariants.size() == 0) {
|
||||
myIsValidByExclusion = false;
|
||||
return selfType;
|
||||
}
|
||||
if (filteredVariants.size() == 1) {
|
||||
return filteredVariants.iterator().next();
|
||||
}
|
||||
return null; // will be handled by variants
|
||||
}
|
||||
return selfType;
|
||||
}
|
||||
|
||||
JsonSchemaType subtypeOfBoth = getSubtypeOfBoth(selfType, otherType);
|
||||
if (subtypeOfBoth == null){
|
||||
myIsValidByExclusion = false;
|
||||
return otherType;
|
||||
}
|
||||
return subtypeOfBoth;
|
||||
}
|
||||
|
||||
private Set<JsonSchemaType> mergeTypeVariantSets(@Nullable Set<JsonSchemaType> self, @Nullable Set<JsonSchemaType> other) {
|
||||
if (self == null) return other;
|
||||
if (other == null) return self;
|
||||
|
||||
Set<JsonSchemaType> resultSet = ContainerUtil.newHashSet(self.size());
|
||||
for (JsonSchemaType type : self) {
|
||||
JsonSchemaType merged = mergeTypes(type, null, other);
|
||||
if (merged != null) resultSet.add(merged);
|
||||
}
|
||||
|
||||
if (resultSet.isEmpty()) {
|
||||
myIsValidByExclusion = false;
|
||||
return other;
|
||||
}
|
||||
|
||||
return resultSet;
|
||||
}
|
||||
|
||||
// peer pointer is not merged!
|
||||
public void mergeValues(@NotNull JsonSchemaObject other) {
|
||||
// we do not copy id, schema
|
||||
@@ -136,11 +226,12 @@ public class JsonSchemaObject {
|
||||
myHtmlDescription = other.myHtmlDescription;
|
||||
}
|
||||
|
||||
if (other.myType != null) myType = other.myType;
|
||||
myType = mergeTypes(myType, other.myType, other.myTypeVariants);
|
||||
|
||||
if (other.myDefault != null) myDefault = other.myDefault;
|
||||
if (other.myRef != null) myRef = other.myRef;
|
||||
if (other.myFormat != null) myFormat = other.myFormat;
|
||||
myTypeVariants = copySet(myTypeVariants, other.myTypeVariants);
|
||||
myTypeVariants = mergeTypeVariantSets(myTypeVariants, other.myTypeVariants);
|
||||
if (other.myMultipleOf != null) myMultipleOf = other.myMultipleOf;
|
||||
if (other.myMaximum != null) myMaximum = other.myMaximum;
|
||||
if (other.myExclusiveMaximumNumber != null) myExclusiveMaximumNumber = other.myExclusiveMaximumNumber;
|
||||
@@ -208,15 +299,6 @@ public class JsonSchemaObject {
|
||||
return target;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static <T> Set<T> copySet(@Nullable Set<T> target, @Nullable Set<T> source) {
|
||||
if (source == null || source.isEmpty()) return target;
|
||||
if (target != null && source.containsAll(target)) return target;
|
||||
if (target == null) target = ContainerUtil.newHashSet(source.size());
|
||||
target.addAll(source);
|
||||
return target;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static <K, V> Map<K, V> copyMap(@Nullable Map<K, V> target, @Nullable Map<K, V> source) {
|
||||
if (source == null || source.isEmpty()) return target;
|
||||
@@ -660,7 +742,7 @@ public class JsonSchemaObject {
|
||||
private static String unescapeJsonString(@NotNull final String text) {
|
||||
try {
|
||||
final String object = String.format("{\"prop\": \"%s\"}", text);
|
||||
return new Gson().fromJson(object, com.google.gson.JsonObject.class).get("prop").getAsString();
|
||||
return new Gson().fromJson(object, JsonObject.class).get("prop").getAsString();
|
||||
} catch (JsonParseException e) {
|
||||
return text;
|
||||
}
|
||||
|
||||
@@ -308,7 +308,10 @@ public class JsonSchemaVariantsTreeBuilder {
|
||||
private static List<JsonSchemaObject> andGroup(@NotNull JsonSchemaObject object, @NotNull List<JsonSchemaObject> group) {
|
||||
List<JsonSchemaObject> list = ContainerUtil.newArrayListWithCapacity(group.size());
|
||||
for (JsonSchemaObject s: group) {
|
||||
list.add(merge(object, s, s));
|
||||
JsonSchemaObject schemaObject = merge(object, s, s);
|
||||
if (schemaObject.isValidByExclusion()) {
|
||||
list.add(schemaObject);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
@@ -369,6 +372,7 @@ public class JsonSchemaVariantsTreeBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JsonSchemaObject merge(@NotNull JsonSchemaObject base,
|
||||
@NotNull JsonSchemaObject other,
|
||||
@NotNull JsonSchemaObject pointTo) {
|
||||
|
||||
@@ -99,7 +99,7 @@ public class JsonSchemaReSharperHighlightingTest extends JsonSchemaHighlightingT
|
||||
public void test012() throws Exception {
|
||||
doTestFiles("test012", "schema012");
|
||||
}
|
||||
public void _test012_2() throws Exception { // TODO bug
|
||||
public void test012_2() throws Exception {
|
||||
doTestFiles("test012_2", "schema012");
|
||||
}
|
||||
public void test012_3() throws Exception {
|
||||
|
||||
@@ -34,6 +34,7 @@ public class JsonSchemaTestSuite extends TestCase {
|
||||
suite.addTestSuite(JsonSchemaCrossReferencesTest.class);
|
||||
suite.addTestSuite(JsonSchemaDocumentationTest.class);
|
||||
suite.addTestSuite(JsonSchemaHighlightingTest.class);
|
||||
suite.addTestSuite(JsonSchemaReSharperHighlightingTest.class);
|
||||
suite.addTestSuite(JsonSchemaPatternComparatorTest.class);
|
||||
suite.addTestSuite(JsonSchemaSelfHighligthingTest.class);
|
||||
suite.addTestSuite(JsonBySchemaCompletionTest.class);
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
|
||||
"a": |true|(0)
|
||||
}
|
||||
|
||||
|
||||
---------------------------------------------------------
|
||||
(0): ReSharper Underlined Error Highlighting: JSON validation failed: Should satisfy at least one of constraints:
|
||||
Expression must be of type 'string'
|
||||
Expression must be of type 'number'
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
|
||||
"a": <warning descr="Type is not allowed. Expected one of: boolean, string.">5</warning>
|
||||
"a": <warning descr="Type is not allowed. Expected: string.">5</warning>
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
|
||||
"a": true
|
||||
"a": <warning descr="Type is not allowed. Expected: string.">true</warning>
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user