mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
json schema annotation fixes related to oneOf: [...]
- if oneOf-schema does not have a detectable type, assume it matches for more detailed check; also, schema does not match if it has an enum, but actual type is object/array - if schemas are different with not-currently-tested properties (i.e. format), they are still different and we should not report that several schemas are matching + tests found checking the data from WEB-25058 Wrong json schema warning
This commit is contained in:
@@ -26,6 +26,7 @@ import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.ThreeState;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import com.jetbrains.jsonSchema.extension.JsonLikePsiWalker;
|
||||
import com.jetbrains.jsonSchema.extension.adapters.JsonArrayValueAdapter;
|
||||
@@ -43,6 +44,8 @@ import java.util.stream.Collectors;
|
||||
* @author Irina.Chernushina on 4/25/2017.
|
||||
*/
|
||||
class JsonSchemaAnnotatorChecker {
|
||||
private static final Set<JsonSchemaType> PRIMITIVE_TYPES =
|
||||
ContainerUtil.set(JsonSchemaType._integer, JsonSchemaType._number, JsonSchemaType._boolean, JsonSchemaType._string, JsonSchemaType._null);
|
||||
private final Map<PsiElement, String> myErrors;
|
||||
private boolean myHadTypeError;
|
||||
|
||||
@@ -351,13 +354,12 @@ class JsonSchemaAnnotatorChecker {
|
||||
}
|
||||
|
||||
private static boolean areSchemaTypesCompatible(@NotNull final JsonSchemaObject schema, @NotNull final JsonSchemaType type) {
|
||||
if (getMatchingSchemaType(schema, type) != null) return true;
|
||||
if (schema.getEnum() != null && (JsonSchemaType._integer.equals(type) ||
|
||||
JsonSchemaType._number.equals(type) || JsonSchemaType._boolean.equals(type) ||
|
||||
JsonSchemaType._string.equals(type))) {
|
||||
return true;
|
||||
if (schema.getEnum() != null) {
|
||||
return PRIMITIVE_TYPES.contains(type);
|
||||
}
|
||||
return false;
|
||||
final JsonSchemaType matchingSchemaType = getMatchingSchemaType(schema, type);
|
||||
if (matchingSchemaType != null) return matchingSchemaType.equals(type);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -550,7 +552,7 @@ class JsonSchemaAnnotatorChecker {
|
||||
private JsonSchemaObject processOneOf(@NotNull JsonValueAdapter value, List<JsonSchemaObject> oneOf) {
|
||||
final Map<PsiElement, String> errors = new HashMap<>();
|
||||
boolean wasTypeError = false;
|
||||
int cntCorrect = 0;
|
||||
final List<JsonSchemaObject> correct = new SmartList<>();
|
||||
JsonSchemaObject current = null;
|
||||
for (JsonSchemaObject object : oneOf) {
|
||||
// skip it if something JS awaited, we do not process it currently
|
||||
@@ -562,7 +564,7 @@ class JsonSchemaAnnotatorChecker {
|
||||
if (checker.isCorrect()) {
|
||||
current = object;
|
||||
errors.clear();
|
||||
++cntCorrect;
|
||||
correct.add(object);
|
||||
}
|
||||
else {
|
||||
if (errors.isEmpty() || wasTypeError && !checker.isHadTypeError() || errors.size() > checker.getErrors().size()) {
|
||||
@@ -573,10 +575,15 @@ class JsonSchemaAnnotatorChecker {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cntCorrect == 1) return current;
|
||||
if (cntCorrect > 0) {
|
||||
if (correct.size() == 1) return current;
|
||||
if (correct.size() > 0) {
|
||||
final JsonSchemaType type = JsonSchemaType.getType(value);
|
||||
if (type != null) error("Validates to more than one variant", value.getDelegate());
|
||||
if (type != null) {
|
||||
// also check maybe some currently not checked properties like format are different with schemes
|
||||
if (!schemesDifferWithNotCheckedProperties(correct)) {
|
||||
error("Validates to more than one variant", value.getDelegate());
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!errors.isEmpty()) {
|
||||
@@ -588,6 +595,10 @@ class JsonSchemaAnnotatorChecker {
|
||||
return current;
|
||||
}
|
||||
|
||||
private static boolean schemesDifferWithNotCheckedProperties(@NotNull final List<JsonSchemaObject> list) {
|
||||
return list.stream().anyMatch(s -> !StringUtil.isEmptyOrSpaces(s.getFormat()));
|
||||
}
|
||||
|
||||
// returns the schema, selected for annotation
|
||||
private JsonSchemaObject processAnyOf(@NotNull JsonValueAdapter value, List<JsonSchemaObject> anyOf) {
|
||||
final Map<PsiElement, String> errors = new HashMap<>();
|
||||
|
||||
@@ -305,8 +305,8 @@ public class JsonSchemaHighlightingTest extends DaemonAnalyzerTestCase {
|
||||
final String subSchema1 = "{\"enum\": [1,2,3,4,5]}";
|
||||
final String subSchema2 = "{\"type\": \"array\", \"items\": {\"properties\": {\"kilo\": {}}, \"additionalProperties\": false}}";
|
||||
final String schema = "{\"properties\": {\"prop\": {\"oneOf\": [" + subSchema1 + ", " + subSchema2 + "]}}}";
|
||||
doTest(schema, "{\"prop\": [{\"kilo\": 20}]}");
|
||||
doTest(schema, "{\"prop\": 5}");
|
||||
//doTest(schema, "{\"prop\": [{\"kilo\": 20}]}");
|
||||
//doTest(schema, "{\"prop\": 5}");
|
||||
doTest(schema, "{\"prop\": [{<warning descr=\"Property 'foxtrot' is not allowed\">\"foxtrot\": 15</warning>, \"kilo\": 20}]}");
|
||||
}
|
||||
|
||||
@@ -512,6 +512,45 @@ public class JsonSchemaHighlightingTest extends DaemonAnalyzerTestCase {
|
||||
doTest(schema, "{\"not_type\": <warning descr=\"String is violating the pattern: '^[a-z]*[0-5]*$'\">\"4a4\"</warning>}");
|
||||
}
|
||||
|
||||
public void testDoNotMarkOneOfThatDiffersWithFormat() throws Exception {
|
||||
final String schema = "{\n" +
|
||||
"\n" +
|
||||
" \"properties\": {\n" +
|
||||
" \"withFormat\": {\n" +
|
||||
" \"type\": \"string\"," +
|
||||
" \"oneOf\": [\n" +
|
||||
" {\n" +
|
||||
" \"format\":\"hostname\"\n" +
|
||||
" },\n" +
|
||||
" {\n" +
|
||||
" \"format\": \"ip4\"\n" +
|
||||
" }\n" +
|
||||
" ]\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
"}";
|
||||
doTest(schema, "{\"withFormat\": \"localhost\"}");
|
||||
}
|
||||
|
||||
public void testAcceptSchemaWithoutType() throws Exception {
|
||||
final String schema = "{\n" +
|
||||
"\n" +
|
||||
" \"properties\": {\n" +
|
||||
" \"withFormat\": {\n" +
|
||||
" \"oneOf\": [\n" +
|
||||
" {\n" +
|
||||
" \"format\":\"hostname\"\n" +
|
||||
" },\n" +
|
||||
" {\n" +
|
||||
" \"format\": \"ip4\"\n" +
|
||||
" }\n" +
|
||||
" ]\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
"}";
|
||||
doTest(schema, "{\"withFormat\": \"localhost\"}");
|
||||
}
|
||||
|
||||
public static String rootObjectRedefinedSchema() {
|
||||
return "{\n" +
|
||||
" \"$schema\": \"http://json-schema.org/draft-04/schema#\",\n" +
|
||||
|
||||
Reference in New Issue
Block a user