diff --git a/json/src/com/jetbrains/jsonSchema/extension/schema/JsonSchemaDefinitionsClimber.java b/json/src/com/jetbrains/jsonSchema/extension/schema/JsonSchemaDefinitionsClimber.java index 203d98843221..616b7b0a660e 100644 --- a/json/src/com/jetbrains/jsonSchema/extension/schema/JsonSchemaDefinitionsClimber.java +++ b/json/src/com/jetbrains/jsonSchema/extension/schema/JsonSchemaDefinitionsClimber.java @@ -25,6 +25,7 @@ import com.jetbrains.jsonSchema.impl.JsonSchemaReader; import com.jetbrains.jsonSchema.impl.JsonSchemaWalker; import org.jetbrains.annotations.NotNull; +import java.util.ArrayDeque; import java.util.ArrayList; import java.util.List; @@ -56,14 +57,21 @@ public class JsonSchemaDefinitionsClimber { final JsonSchemaWalker.CompletionSchemesConsumer consumer = new JsonSchemaWalker.CompletionSchemesConsumer() { @Override public void consume(boolean isName, @NotNull JsonSchemaObject schema) { - processDefinitionAddress(schema, myShortPropertyName); + int cnt = 1000; + final List list = new ArrayList<>(); + final ArrayDeque queue = new ArrayDeque<>(); + queue.add(schema); + while (!queue.isEmpty() && cnt > 0) { + final JsonSchemaObject object = queue.removeFirst(); + list.add(object); + if (object.getAllOf() != null) queue.addAll(object.getAllOf()); + if (object.getAnyOf() != null) queue.addAll(object.getAnyOf()); + if (object.getOneOf() != null) queue.addAll(object.getOneOf()); + --cnt; + } - List list = new ArrayList<>(); - if (schema.getAllOf() != null) list.addAll(schema.getAllOf()); - if (schema.getAnyOf() != null) list.addAll(schema.getAnyOf()); - if (schema.getOneOf() != null) list.addAll(schema.getOneOf()); - for (JsonSchemaObject schemaObject : list) { - processDefinitionAddress(schemaObject, myShortPropertyName); + for (JsonSchemaObject object : list) { + processDefinitionAddress(object, myShortPropertyName); } } }; diff --git a/json/src/com/jetbrains/jsonSchema/impl/JsonSchemaWalker.java b/json/src/com/jetbrains/jsonSchema/impl/JsonSchemaWalker.java index 0cd4daadb89f..fc7c4fc3b4ed 100644 --- a/json/src/com/jetbrains/jsonSchema/impl/JsonSchemaWalker.java +++ b/json/src/com/jetbrains/jsonSchema/impl/JsonSchemaWalker.java @@ -68,7 +68,7 @@ public class JsonSchemaWalker { public static Pair, String> buildSteps(@NotNull String nameInSchema) { final String[] chain = JsonSchemaExportedDefinitions.normalizeId(nameInSchema).replace("\\", "/").split("/"); - final List steps = Arrays.stream(chain).map(item -> new Step(StateType._unknown, new PropertyTransition(item))) + final List steps = Arrays.stream(chain).filter(s -> !s.isEmpty()).map(item -> new Step(StateType._unknown, new PropertyTransition(item))) .collect(Collectors.toList()); return Pair.create(steps, chain[chain.length - 1]); } diff --git a/json/tests/test/com/jetbrains/jsonSchema/JsonSchemaCrossReferencesTest.java b/json/tests/test/com/jetbrains/jsonSchema/JsonSchemaCrossReferencesTest.java index 147396c81643..31022f2aa20a 100644 --- a/json/tests/test/com/jetbrains/jsonSchema/JsonSchemaCrossReferencesTest.java +++ b/json/tests/test/com/jetbrains/jsonSchema/JsonSchemaCrossReferencesTest.java @@ -368,6 +368,62 @@ public class JsonSchemaCrossReferencesTest extends JsonSchemaHeavyAbstractTest { }); } + public void testNavigateToPropertyDefinitionNestedDefinitions() throws Exception { + skeleton(new Callback() { + @Override + public void registerSchemes() { + final String moduleDir = getModuleDir(getProject()); + final List patterns = Collections.singletonList( + new JsonSchemaMappingsConfigurationBase.Item("testNestedDefinitionsNavigation.json", true, false)); + addSchema(new JsonSchemaMappingsConfigurationBase.SchemaInfo("one", moduleDir + "/nestedDefinitionsSchema.json", false, patterns)); + } + + @Override + public void configureFiles() throws Exception { + configureByFiles(null, "/testNestedDefinitionsNavigation.json", "/nestedDefinitionsSchema.json"); + } + + @Override + public void doCheck() { + int offset = myEditor.getCaretModel().getPrimaryCaret().getOffset(); + final PsiReference referenceAt = myFile.findReferenceAt(offset); + Assert.assertNotNull(referenceAt); + final PsiElement resolve = referenceAt.resolve(); + Assert.assertNotNull(resolve); + Assert.assertEquals("nestedDefinitionsSchema.json", resolve.getContainingFile().getName()); + Assert.assertEquals("\"definitions\"", resolve.getText()); + } + }); + } + + public void testNavigateToAllOfOneOfDefinitions() throws Exception { + skeleton(new Callback() { + @Override + public void registerSchemes() { + final String moduleDir = getModuleDir(getProject()); + final List patterns = Collections.singletonList( + new JsonSchemaMappingsConfigurationBase.Item("testNestedAllOfOneOfDefinitionsSchema.json", true, false)); + addSchema(new JsonSchemaMappingsConfigurationBase.SchemaInfo("one", moduleDir + "/nestedAllOfOneOfDefinitionsSchema.json", false, patterns)); + } + + @Override + public void configureFiles() throws Exception { + configureByFiles(null, "/testNestedAllOfOneOfDefinitionsSchema.json", "/nestedAllOfOneOfDefinitionsSchema.json"); + } + + @Override + public void doCheck() { + int offset = myEditor.getCaretModel().getPrimaryCaret().getOffset(); + final PsiReference referenceAt = myFile.findReferenceAt(offset); + Assert.assertNotNull(referenceAt); + final PsiElement resolve = referenceAt.resolve(); + Assert.assertNotNull(resolve); + Assert.assertEquals("nestedAllOfOneOfDefinitionsSchema.json", resolve.getContainingFile().getName()); + Assert.assertEquals("\"begriff\"", resolve.getText()); + } + }); + } + @NotNull private static String getModuleDir(@NotNull final Project project) { String moduleDir = null; diff --git a/json/tests/testData/jsonSchema/crossReferences/nestedAllOfOneOfDefinitionsSchema.json b/json/tests/testData/jsonSchema/crossReferences/nestedAllOfOneOfDefinitionsSchema.json new file mode 100644 index 000000000000..cbbbc9b984cd --- /dev/null +++ b/json/tests/testData/jsonSchema/crossReferences/nestedAllOfOneOfDefinitionsSchema.json @@ -0,0 +1,36 @@ +{ + "definitions": { + "here": { + "properties": { + "definitions": { + "enum": [1,2] + } + } + }, + "there": { + "properties": { + "begriff": { + "enum": ["one", "two"] + } + } + }, + "middleDef": { + "$ref": "#/definitions/here" + }, + "mittel": { + "oneOf": [ + {"$ref": "#/definitions/there"}, + {"$ref": "#/definitions/here"} + ] + } + }, + "type": "object", + "properties": { + "middle" : { + "allOf" : [ + {"$ref": "#/definitions/middleDef"}, + {"$ref": "#/definitions/mittel"} + ] + } + } +} \ No newline at end of file diff --git a/json/tests/testData/jsonSchema/crossReferences/nestedDefinitionsSchema.json b/json/tests/testData/jsonSchema/crossReferences/nestedDefinitionsSchema.json new file mode 100644 index 000000000000..0650e88dd3fb --- /dev/null +++ b/json/tests/testData/jsonSchema/crossReferences/nestedDefinitionsSchema.json @@ -0,0 +1,20 @@ +{ + "definitions": { + "here": { + "enum": [1,2] + }, + "middle": { + "properties": { + "definitions": { + "$ref": "#/definitions/here" + } + } + } + }, + "type": "object", + "properties": { + "middle" : { + "$ref": "#/definitions/middle" + } + } +} \ No newline at end of file diff --git a/json/tests/testData/jsonSchema/crossReferences/testNestedAllOfOneOfDefinitionsSchema.json b/json/tests/testData/jsonSchema/crossReferences/testNestedAllOfOneOfDefinitionsSchema.json new file mode 100644 index 000000000000..b7afee585381 --- /dev/null +++ b/json/tests/testData/jsonSchema/crossReferences/testNestedAllOfOneOfDefinitionsSchema.json @@ -0,0 +1,5 @@ +{ + "middle": { + "begriff": "one" + } +} \ No newline at end of file diff --git a/json/tests/testData/jsonSchema/crossReferences/testNestedDefinitionsNavigation.json b/json/tests/testData/jsonSchema/crossReferences/testNestedDefinitionsNavigation.json new file mode 100644 index 000000000000..55958e9db5a0 --- /dev/null +++ b/json/tests/testData/jsonSchema/crossReferences/testNestedDefinitionsNavigation.json @@ -0,0 +1,5 @@ +{ + "middle": { + "definitions": 1 + } +} \ No newline at end of file