diff --git a/json/intellij.json.iml b/json/intellij.json.iml
index 5d8690af9e46..240d9ea3b74f 100644
--- a/json/intellij.json.iml
+++ b/json/intellij.json.iml
@@ -12,7 +12,6 @@
-
diff --git a/json/src/com/intellij/json/JsonUtil.java b/json/src/com/intellij/json/JsonUtil.java
index eaa9685b8565..1245d73eaf4c 100644
--- a/json/src/com/intellij/json/JsonUtil.java
+++ b/json/src/com/intellij/json/JsonUtil.java
@@ -2,6 +2,7 @@ package com.intellij.json;
import com.intellij.json.psi.*;
import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiElement;
import com.intellij.util.ObjectUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -65,4 +66,20 @@ public class JsonUtil {
final JsonStringLiteral literal = getPropertyValueOfType(object, name, JsonStringLiteral.class);
return literal == null ? null : Collections.singletonList(StringUtil.unquoteString(literal.getText()));
}
+
+ public static boolean isArrayElement(@NotNull PsiElement element) {
+ return element instanceof JsonValue && element.getParent() instanceof JsonArray;
+ }
+
+ public static int getArrayIndexOfItem(@NotNull PsiElement e) {
+ PsiElement parent = e.getParent();
+ if (!(parent instanceof JsonArray)) return -1;
+ List elements = ((JsonArray)parent).getValueList();
+ for (int i = 0; i < elements.size(); i++) {
+ if (e == elements.get(i)) {
+ return i;
+ }
+ }
+ return -1;
+ }
}
diff --git a/json/src/com/intellij/json/breadcrumbs/JsonBreadcrumbsProvider.java b/json/src/com/intellij/json/breadcrumbs/JsonBreadcrumbsProvider.java
index 2684bcbe1fb6..9d376a7a3aef 100644
--- a/json/src/com/intellij/json/breadcrumbs/JsonBreadcrumbsProvider.java
+++ b/json/src/com/intellij/json/breadcrumbs/JsonBreadcrumbsProvider.java
@@ -1,17 +1,19 @@
package com.intellij.json.breadcrumbs;
import com.intellij.json.JsonLanguage;
+import com.intellij.json.JsonUtil;
+import com.intellij.json.psi.JsonProperty;
import com.intellij.lang.Language;
import com.intellij.psi.PsiElement;
-import com.intellij.xml.breadcrumbs.BreadcrumbsInfoProvider;
-import com.intellij.json.psi.JsonProperty;
+import com.intellij.ui.breadcrumbs.BreadcrumbsProvider;
+import com.jetbrains.jsonSchema.impl.JsonSchemaDocumentationProvider;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author Mikhail Golubev
*/
-public class JsonBreadcrumbsProvider extends BreadcrumbsInfoProvider {
+public class JsonBreadcrumbsProvider implements BreadcrumbsProvider {
private static final Language[] LANGUAGES = new Language[]{JsonLanguage.INSTANCE};
@Override
@@ -21,7 +23,7 @@ public class JsonBreadcrumbsProvider extends BreadcrumbsInfoProvider {
@Override
public boolean acceptElement(@NotNull PsiElement e) {
- return e instanceof JsonProperty;
+ return e instanceof JsonProperty || JsonUtil.isArrayElement(e);
}
@NotNull
@@ -30,20 +32,16 @@ public class JsonBreadcrumbsProvider extends BreadcrumbsInfoProvider {
if (e instanceof JsonProperty) {
return ((JsonProperty)e).getName();
}
- //else if (isArrayElement(e)) {
- // List elements = ((JsonArray)e.getParent()).getValueList();
- // for (int i = 0; i < elements.size(); i++) {
- // if (e == elements.get(i)) {
- // return String.valueOf(i);
- // }
- // }
- //}
- throw new AssertionError("Breadcrumbs can be extracted only from JsonProperty elements");
+ else if (JsonUtil.isArrayElement(e)) {
+ int i = JsonUtil.getArrayIndexOfItem(e);
+ if (i != -1) return String.valueOf(i);
+ }
+ throw new AssertionError("Breadcrumbs can be extracted only from JsonProperty elements or JsonArray child items");
}
@Nullable
@Override
public String getElementTooltip(@NotNull PsiElement e) {
- return null;
+ return JsonSchemaDocumentationProvider.findSchemaAndGenerateDoc(e, null, true);
}
}
diff --git a/json/src/com/intellij/json/navigation/JsonQualifiedNameProvider.java b/json/src/com/intellij/json/navigation/JsonQualifiedNameProvider.java
index 45ca4daf10e3..e6773e95ed81 100644
--- a/json/src/com/intellij/json/navigation/JsonQualifiedNameProvider.java
+++ b/json/src/com/intellij/json/navigation/JsonQualifiedNameProvider.java
@@ -1,6 +1,8 @@
package com.intellij.json.navigation;
import com.intellij.ide.actions.QualifiedNameProvider;
+import com.intellij.json.JsonUtil;
+import com.intellij.json.psi.JsonArray;
import com.intellij.json.psi.JsonElement;
import com.intellij.json.psi.JsonProperty;
import com.intellij.openapi.project.Project;
@@ -9,8 +11,6 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.Nullable;
-import java.util.LinkedList;
-
/**
* @author Mikhail Golubev
*/
@@ -27,13 +27,30 @@ public class JsonQualifiedNameProvider implements QualifiedNameProvider {
if (!(element instanceof JsonElement)) {
return null;
}
- final LinkedList qualifiers = new LinkedList<>();
- JsonProperty parentProperty = PsiTreeUtil.getNonStrictParentOfType(element, JsonProperty.class);
+ JsonElement parentProperty = PsiTreeUtil.getNonStrictParentOfType(element, JsonProperty.class, JsonArray.class);
+ StringBuilder builder = new StringBuilder();
while (parentProperty != null) {
- qualifiers.addFirst(parentProperty.getName());
- parentProperty = PsiTreeUtil.getParentOfType(parentProperty, JsonProperty.class);
+ if (parentProperty instanceof JsonProperty) {
+ builder.insert(0, parentProperty.getName());
+ builder.insert(0, ".");
+ }
+ else {
+ int index = JsonUtil.getArrayIndexOfItem(element instanceof JsonProperty ? element.getParent() : element);
+ if (index == -1) return null;
+ builder.insert(0, "[" + index + "]");
+ }
+ element = parentProperty;
+ parentProperty = PsiTreeUtil.getParentOfType(parentProperty, JsonProperty.class, JsonArray.class);
}
- return qualifiers.isEmpty() ? null : StringUtil.join(qualifiers, ".");
+
+ if (builder.length() == 0) return null;
+
+ // if the first operation is array indexing, we insert the 'root' element $
+ if (builder.charAt(0) == '[') {
+ builder.insert(0, "$");
+ }
+
+ return StringUtil.trimStart(builder.toString(), ".");
}
@Override
diff --git a/json/src/com/jetbrains/jsonSchema/impl/JsonSchemaDocumentationProvider.java b/json/src/com/jetbrains/jsonSchema/impl/JsonSchemaDocumentationProvider.java
index 85234b05ecc1..deb24a1d69ff 100644
--- a/json/src/com/jetbrains/jsonSchema/impl/JsonSchemaDocumentationProvider.java
+++ b/json/src/com/jetbrains/jsonSchema/impl/JsonSchemaDocumentationProvider.java
@@ -36,7 +36,7 @@ public class JsonSchemaDocumentationProvider implements DocumentationProvider {
}
@Nullable
- private static String findSchemaAndGenerateDoc(PsiElement element, @Nullable PsiElement originalElement, final boolean preferShort) {
+ public static String findSchemaAndGenerateDoc(PsiElement element, @Nullable PsiElement originalElement, final boolean preferShort) {
element = ObjectUtils.coalesce(originalElement, element);
final PsiFile containingFile = element.getContainingFile();
if (containingFile == null) return null;
diff --git a/json/tests/test/com/intellij/json/JsonBreadcrumbsTest.java b/json/tests/test/com/intellij/json/JsonBreadcrumbsTest.java
new file mode 100644
index 000000000000..9416a649def0
--- /dev/null
+++ b/json/tests/test/com/intellij/json/JsonBreadcrumbsTest.java
@@ -0,0 +1,19 @@
+// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package com.intellij.json;
+
+import com.intellij.ui.components.breadcrumbs.Crumb;
+
+import java.util.List;
+
+public class JsonBreadcrumbsTest extends JsonTestCase {
+
+ private void doTest(String... components) {
+ myFixture.configureByFile("breadcrumbs/" + getTestName(false) + ".json");
+ List caret = myFixture.getBreadcrumbsAtCaret();
+ assertOrderedEquals(caret.stream().map(Crumb::getText).toArray(String[]::new), components);
+ }
+
+ public void testComplexItems() {
+ doTest("foo", "bar", "0", "0", "baz");
+ }
+}
diff --git a/json/tests/test/com/intellij/json/JsonNavigationTest.java b/json/tests/test/com/intellij/json/JsonNavigationTest.java
index 1ca4acf83f8d..da610a6bd854 100644
--- a/json/tests/test/com/intellij/json/JsonNavigationTest.java
+++ b/json/tests/test/com/intellij/json/JsonNavigationTest.java
@@ -15,6 +15,6 @@ public class JsonNavigationTest extends JsonTestCase {
final PsiElement element = myFixture.getElementAtCaret();
assertInstanceOf(element, JsonProperty.class);
final String qualifiedName = CopyReferenceAction.elementToFqn(element);
- assertEquals("foo.bar.baz", qualifiedName);
+ assertEquals("foo.bar[0][0].baz", qualifiedName);
}
}
diff --git a/json/tests/testData/breadcrumbs/ComplexItems.json b/json/tests/testData/breadcrumbs/ComplexItems.json
new file mode 100644
index 000000000000..c5f889219193
--- /dev/null
+++ b/json/tests/testData/breadcrumbs/ComplexItems.json
@@ -0,0 +1,11 @@
+{
+ "foo": {
+ "bar": [
+ [
+ {
+ "baz": null
+ }
+ ]
+ ]
+ }
+}
\ No newline at end of file