WEB-32243 JSON schema: JSON pointer refs with array items are ignored

This commit is contained in:
Anton Lobov
2018-04-18 16:05:33 +02:00
parent 1a14bea670
commit db30681e70
6 changed files with 84 additions and 35 deletions
@@ -3,6 +3,7 @@ package com.jetbrains.jsonSchema.impl;
import com.google.common.base.Predicates;
import com.intellij.json.JsonBundle;
import com.intellij.json.psi.JsonContainer;
import com.intellij.json.psi.JsonObject;
import com.intellij.json.psi.JsonProperty;
import com.intellij.openapi.util.Pair;
@@ -344,12 +345,12 @@ class JsonSchemaAnnotatorChecker {
continue;
}
final JsonObject element = prop.getJsonObject();
if (!element.isValid()) {
final JsonContainer element = prop.getJsonObject();
if (!(element instanceof JsonObject) || !element.isValid()) {
continue;
}
final JsonProperty pattern = element.findProperty("pattern");
final JsonProperty pattern = ((JsonObject)element).findProperty("pattern");
if (pattern != null) {
error(StringUtil.convertLineSeparators(patternError), pattern.getValue());
}
@@ -357,11 +358,11 @@ class JsonSchemaAnnotatorChecker {
}
private void reportInvalidPatternProperties(JsonSchemaObject schema) {
final Map<JsonObject, String> invalidPatternProperties = schema.getInvalidPatternProperties();
final Map<JsonContainer, String> invalidPatternProperties = schema.getInvalidPatternProperties();
if (invalidPatternProperties == null) return;
for (Map.Entry<JsonObject, String> entry : invalidPatternProperties.entrySet()) {
final JsonObject element = entry.getKey();
for (Map.Entry<JsonContainer, String> entry : invalidPatternProperties.entrySet()) {
final JsonContainer element = entry.getKey();
if (element == null || !element.isValid()) continue;
final PsiElement parent = element.getParent();
if (parent instanceof JsonProperty) {
@@ -3,7 +3,7 @@ package com.jetbrains.jsonSchema.impl;
import com.google.gson.Gson;
import com.google.gson.JsonParseException;
import com.intellij.json.psi.JsonObject;
import com.intellij.json.psi.JsonContainer;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.util.Pair;
@@ -31,7 +31,7 @@ public class JsonSchemaObject {
@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;
@NotNull private final JsonContainer myJsonObject;
@Nullable private Map<String, JsonSchemaObject> myDefinitionsMap;
@NotNull private Map<String, JsonSchemaObject> myProperties;
@@ -94,7 +94,7 @@ public class JsonSchemaObject {
@Nullable private JsonSchemaObject myElse;
private boolean myShouldValidateAgainstJSType;
public JsonSchemaObject(@NotNull JsonObject object) {
public JsonSchemaObject(@NotNull JsonContainer object) {
myJsonObject = object;
myProperties = new HashMap<>();
}
@@ -191,7 +191,7 @@ public class JsonSchemaObject {
}
@NotNull
public JsonObject getJsonObject() {
public JsonContainer getJsonObject() {
return myJsonObject;
}
@@ -640,7 +640,7 @@ public class JsonSchemaObject {
}
@Nullable
public Map<JsonObject, String> getInvalidPatternProperties() {
public Map<JsonContainer, String> getInvalidPatternProperties() {
if (myPatternProperties != null) {
final Map<String, String> patterns = myPatternProperties.getInvalidPatterns();
@@ -76,13 +76,25 @@ public class JsonSchemaReader {
while (!myQueue.isEmpty()) {
final JsonSchemaObject currentSchema = myQueue.removeFirst();
final JsonObject jsonObject = currentSchema.getJsonObject();
final List<JsonProperty> list = jsonObject.getPropertyList();
for (JsonProperty property : list) {
if (StringUtil.isEmptyOrSpaces(property.getName()) || property.getValue() == null) continue;
final MyReader reader = READERS_MAP.get(property.getName());
if (reader != null) reader.read(property.getValue(), currentSchema, myQueue);
else readSingleDefinition(property.getName(), property.getValue(), currentSchema);
final JsonContainer jsonObject = currentSchema.getJsonObject();
if (jsonObject instanceof JsonObject) {
final List<JsonProperty> list = ((JsonObject)jsonObject).getPropertyList();
for (JsonProperty property : list) {
if (StringUtil.isEmptyOrSpaces(property.getName()) || property.getValue() == null) continue;
final MyReader reader = READERS_MAP.get(property.getName());
if (reader != null) {
reader.read(property.getValue(), currentSchema, myQueue);
}
else {
readSingleDefinition(property.getName(), property.getValue(), currentSchema);
}
}
}
else if (jsonObject instanceof JsonArray) {
List<JsonValue> values = ((JsonArray)jsonObject).getValueList();
for (int i = 0; i < values.size(); i++) {
readSingleDefinition(String.valueOf(i), values.get(i), currentSchema);
}
}
if (currentSchema.getId() != null) myIds.put(currentSchema.getId(), currentSchema);
@@ -95,8 +107,8 @@ public class JsonSchemaReader {
}
private void readSingleDefinition(@NotNull String name, @NotNull JsonValue value, @NotNull JsonSchemaObject schema) {
if (value instanceof JsonObject) {
final JsonSchemaObject defined = new JsonSchemaObject((JsonObject)value);
if (value instanceof JsonContainer) {
final JsonSchemaObject defined = new JsonSchemaObject((JsonContainer)value);
myQueue.add(defined);
Map<String, JsonSchemaObject> definitions = schema.getDefinitionsMap();
if (definitions == null) schema.setDefinitionsMap(definitions = new HashMap<>());
@@ -15,10 +15,7 @@
*/
package com.jetbrains.jsonSchema.impl;
import com.intellij.json.psi.JsonArray;
import com.intellij.json.psi.JsonObject;
import com.intellij.json.psi.JsonProperty;
import com.intellij.json.psi.JsonValue;
import com.intellij.json.psi.*;
import com.intellij.openapi.util.Ref;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
@@ -135,7 +132,7 @@ public class JsonSchemaResolver {
@Nullable
private static JsonValue getSchemaNavigationItem(@Nullable final JsonSchemaObject schema) {
if (schema == null) return null;
final JsonObject jsonObject = schema.getJsonObject();
final JsonContainer jsonObject = schema.getJsonObject();
if (jsonObject.getParent() instanceof JsonProperty) {
return ((JsonProperty)jsonObject.getParent()).getNameElement();
}
@@ -15,6 +15,7 @@
*/
package com.jetbrains.jsonSchema.impl;
import com.intellij.json.psi.JsonContainer;
import com.intellij.json.psi.JsonObject;
import com.intellij.json.psi.JsonProperty;
import com.intellij.openapi.diagnostic.Logger;
@@ -95,7 +96,7 @@ public class JsonSchemaVariantsTreeBuilder {
}
private static void expandChildSchema(@NotNull JsonSchemaTreeNode node, @NotNull JsonSchemaObject childSchema, @NotNull JsonSchemaService service) {
final JsonObject element = childSchema.getJsonObject();
final JsonContainer element = childSchema.getJsonObject();
if (interestingSchema(childSchema)) {
final Operation operation =
CachedValuesManager.getManager(element.getProject())
@@ -115,9 +116,18 @@ public class JsonSchemaVariantsTreeBuilder {
public static List<Step> buildSteps(@NotNull String nameInSchema) {
final List<String> chain = StringUtil.split(JsonSchemaService.normalizeId(nameInSchema).replace("\\", "/"), "/");
return chain.stream().filter(s -> !s.isEmpty())
.map(item -> Step.createPropertyStep(item))
.collect(Collectors.toList());
List<Step> steps = ContainerUtil.newArrayListWithCapacity(chain.size());
for (String s: chain) {
if (!StringUtil.isEmpty(s)) {
try {
steps.add(Step.createArrayElementStep(Integer.parseInt(s)));
}
catch (NumberFormatException e) {
steps.add(Step.createPropertyStep(s));
}
}
}
return steps;
}
static abstract class Operation {
@@ -132,10 +142,10 @@ public class JsonSchemaVariantsTreeBuilder {
myChildOperations = new ArrayList<>();
}
protected abstract void map(@NotNull Set<JsonObject> visited);
protected abstract void map(@NotNull Set<JsonContainer> visited);
protected abstract void reduce();
public void doMap(@NotNull final Set<JsonObject> visited) {
public void doMap(@NotNull final Set<JsonContainer> visited) {
map(visited);
for (Operation operation : myChildOperations) {
operation.doMap(visited);
@@ -197,7 +207,7 @@ public class JsonSchemaVariantsTreeBuilder {
}
@Override
public void map(@NotNull final Set<JsonObject> visited) {
public void map(@NotNull final Set<JsonContainer> visited) {
JsonSchemaObject current = mySourceNode;
while (!StringUtil.isEmptyOrSpaces(current.getRef())) {
final JsonSchemaObject definition = getSchemaFromDefinition(current, myService);
@@ -234,7 +244,7 @@ public class JsonSchemaVariantsTreeBuilder {
}
@Override
public void map(@NotNull final Set<JsonObject> visited) {
public void map(@NotNull final Set<JsonContainer> visited) {
assert mySourceNode.getAllOf() != null;
myChildOperations.addAll(mySourceNode.getAllOf().stream()
.map(sourceNode -> new ProcessDefinitionsOperation(sourceNode, myService)).collect(Collectors.toList()));
@@ -313,7 +323,7 @@ public class JsonSchemaVariantsTreeBuilder {
}
@Override
public void map(@NotNull final Set<JsonObject> visited) {
public void map(@NotNull final Set<JsonContainer> visited) {
assert mySourceNode.getOneOf() != null;
myChildOperations.addAll(mySourceNode.getOneOf().stream()
.map(sourceNode -> new ProcessDefinitionsOperation(sourceNode, myService)).collect(Collectors.toList()));
@@ -342,7 +352,7 @@ public class JsonSchemaVariantsTreeBuilder {
}
@Override
public void map(@NotNull final Set<JsonObject> visited) {
public void map(@NotNull final Set<JsonContainer> visited) {
assert mySourceNode.getAnyOf() != null;
myChildOperations.addAll(mySourceNode.getAnyOf().stream()
.map(sourceNode -> new ProcessDefinitionsOperation(sourceNode, myService)).collect(Collectors.toList()));
@@ -779,4 +779,33 @@ public class JsonSchemaHighlightingTest extends DaemonAnalyzerTestCase {
doTest(schema, "{\"type\": <warning>\"doog\"</warning>}");
doTest(schema, "{\"type\": <warning>\"ko\"</warning>}");
}
public void testArrayRefs() throws Exception {
@Language("JSON") String schema = "{\n" +
" \"myDefs\": {\n" +
" \"myArray\": [\n" +
" {\n" +
" \"type\": \"number\"\n" +
" },\n" +
" {\n" +
" \"type\": \"string\"\n" +
" }\n" +
" ]\n" +
" },\n" +
" \"type\": \"array\",\n" +
" \"items\": [\n" +
" {\n" +
" \"$ref\": \"#/myDefs/myArray/0\"\n" +
" },\n" +
" {\n" +
" \"$ref\": \"#/myDefs/myArray/1\"\n" +
" }\n" +
" ]\n" +
"}";
doTest(schema, "[1, <warning>2</warning>]");
doTest(schema, "[<warning>\"1\"</warning>, <warning>2</warning>]");
doTest(schema, "[<warning>\"1\"</warning>, \"2\"]");
doTest(schema, "[1, \"2\"]");
}
}