mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
json schema: resolve array pointers, validate additional items
Fixes WEB-32242
This commit is contained in:
@@ -457,6 +457,9 @@ class JsonSchemaAnnotatorChecker {
|
||||
if (!Boolean.TRUE.equals(schema.getAdditionalItemsAllowed())) {
|
||||
error("Additional items are not allowed", arrayValue.getDelegate());
|
||||
}
|
||||
else if (schema.getAdditionalItemsSchema() != null) {
|
||||
checkObjectBySchemaRecordErrors(schema.getAdditionalItemsSchema(), arrayValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -28,6 +29,8 @@ import java.util.stream.Collectors;
|
||||
public class JsonSchemaObject {
|
||||
@NonNls public static final String DEFINITIONS = "definitions";
|
||||
@NonNls public static final String PROPERTIES = "properties";
|
||||
@NonNls public static final String ITEMS = "items";
|
||||
@NonNls public static final String ADDITIONAL_ITEMS = "additionalItems";
|
||||
@NonNls public static final String X_INTELLIJ_HTML_DESCRIPTION = "x-intellij-html-description";
|
||||
@NotNull private final JsonObject myJsonObject;
|
||||
@Nullable private Map<String, JsonSchemaObject> myDefinitionsMap;
|
||||
@@ -641,12 +644,54 @@ public class JsonSchemaObject {
|
||||
current = current.getProperties().get(parts.get(++i));
|
||||
continue;
|
||||
}
|
||||
|
||||
Pair<JsonSchemaObject, Integer> arrayResult = ObjectUtils.coalesce(
|
||||
handleArrayItem(ITEMS, parts, i, current.getItemsSchema(), current.getItemsSchemaList()),
|
||||
handleArrayItem(ADDITIONAL_ITEMS, parts, i, current.getAdditionalItemsSchema(), ContainerUtil.emptyList()));
|
||||
if (arrayResult != null) {
|
||||
//noinspection AssignmentToForLoopParameter
|
||||
i = arrayResult.second;
|
||||
current = arrayResult.first;
|
||||
continue;
|
||||
}
|
||||
current = current.getDefinitionsMap() == null ? null : current.getDefinitionsMap().get(part);
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Pair<JsonSchemaObject, Integer> handleArrayItem(@NotNull String name,
|
||||
List<String> parts,
|
||||
int i,
|
||||
@Nullable JsonSchemaObject arraySchema,
|
||||
@Nullable List<JsonSchemaObject> arraySchemaList) {
|
||||
final String part = parts.get(i);
|
||||
if (!name.equals(part)) {
|
||||
return null;
|
||||
}
|
||||
if (i == (parts.size() - 1)) {
|
||||
if (arraySchema != null) {
|
||||
return Pair.create(arraySchema, i);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Integer next = tryParseInt(parts.get(++i));
|
||||
if (arraySchemaList != null && next != null && next >= 0 && next < arraySchemaList.size()) {
|
||||
return Pair.create(arraySchemaList.get(next), i);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Integer tryParseInt(String s) {
|
||||
try {
|
||||
return Integer.parseInt(s);
|
||||
}
|
||||
catch (Exception __) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object o) {
|
||||
if (this == o) return true;
|
||||
|
||||
@@ -155,8 +155,8 @@ public class JsonSchemaReader {
|
||||
READERS_MAP.put("pattern", (element, object, queue) -> {
|
||||
if (element instanceof JsonStringLiteral) object.setPattern(StringUtil.unquoteString(element.getText()));
|
||||
});
|
||||
READERS_MAP.put("additionalItems", createAdditionalItems());
|
||||
READERS_MAP.put("items", createItems());
|
||||
READERS_MAP.put(JsonSchemaObject.ADDITIONAL_ITEMS, createAdditionalItems());
|
||||
READERS_MAP.put(JsonSchemaObject.ITEMS, createItems());
|
||||
READERS_MAP.put("contains", createContains());
|
||||
READERS_MAP.put("maxItems", (element, object, queue) -> {
|
||||
if (element instanceof JsonNumberLiteral) object.setMaxItems((int)((JsonNumberLiteral)element).getValue());
|
||||
|
||||
@@ -546,6 +546,78 @@ public class JsonSchemaHighlightingTest extends DaemonAnalyzerTestCase {
|
||||
doTest(schema, "{\"withFormat\": \"localhost\"}");
|
||||
}
|
||||
|
||||
public void testArrayItemReference() throws Exception {
|
||||
@Language("JSON") final String schema = "{\n" +
|
||||
" \"items\": [\n" +
|
||||
" {\n" +
|
||||
" \"type\": \"integer\"\n" +
|
||||
" },\n" +
|
||||
" {\n" +
|
||||
" \"$ref\": \"#/items/0\"\n" +
|
||||
" }\n" +
|
||||
" ]\n" +
|
||||
"}";
|
||||
doTest(schema, "[1, 2]");
|
||||
doTest(schema, "[1, <warning>\"foo\"</warning>]");
|
||||
}
|
||||
|
||||
public void testArrayReference() throws Exception {
|
||||
@Language("JSON") final String schema = "{\n" +
|
||||
" \"definitions\": {\n" +
|
||||
" \"options\": {\n" +
|
||||
" \"type\": \"array\",\n" +
|
||||
" \"items\": {\n" +
|
||||
" \"type\": \"number\"\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
" },\n" +
|
||||
" \"items\":{\n" +
|
||||
" \"$ref\": \"#/definitions/options/items\"\n" +
|
||||
" }\n" +
|
||||
" \n" +
|
||||
"}";
|
||||
doTest(schema, "[2, 3 ,4]");
|
||||
doTest(schema, "[2, <warning>\"3\"</warning>]");
|
||||
}
|
||||
|
||||
public void testSelfArrayReferenceDoesNotThrowSOE() throws Exception {
|
||||
@Language("JSON") final String schema = "{\n" +
|
||||
" \"items\": [\n" +
|
||||
" {\n" +
|
||||
" \"$ref\": \"#/items/0\"\n" +
|
||||
" }\n" +
|
||||
" ]\n" +
|
||||
"}";
|
||||
doTest(schema, "[]");
|
||||
}
|
||||
|
||||
public void testValidateAdditionalItems() throws Exception {
|
||||
@Language("JSON") final String schema = "{\n" +
|
||||
" \"definitions\": {\n" +
|
||||
" \"options\": {\n" +
|
||||
" \"type\": \"array\",\n" +
|
||||
" \"items\": {\n" +
|
||||
" \"type\": \"number\"\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
" },\n" +
|
||||
" \"items\": [\n" +
|
||||
" {\n" +
|
||||
" \"type\": \"boolean\"\n" +
|
||||
" },\n" +
|
||||
" {\n" +
|
||||
" \"type\": \"boolean\"\n" +
|
||||
" }\n" +
|
||||
" ],\n" +
|
||||
" \"additionalItems\": {\n" +
|
||||
" \"$ref\": \"#/definitions/options/items\"\n" +
|
||||
" }\n" +
|
||||
"}";
|
||||
doTest(schema, "[true, true]");
|
||||
doTest(schema, "[true, true, 1, 2, 3]");
|
||||
doTest(schema, "[true, true, 1, <warning>\"2\"</warning>]");
|
||||
}
|
||||
|
||||
public static String rootObjectRedefinedSchema() {
|
||||
return "{\n" +
|
||||
" \"$schema\": \"http://json-schema.org/draft-04/schema#\",\n" +
|
||||
|
||||
Reference in New Issue
Block a user