WEB-31883, WEB-31989: array indexes in JSON breadcrumbs/qualified names

This commit is contained in:
Anton Lobov
2018-03-27 12:04:51 +02:00
parent 5d16245cd6
commit 802c4c6676
8 changed files with 85 additions and 24 deletions
-1
View File
@@ -12,7 +12,6 @@
<orderEntry type="module" module-name="intellij.platform.core" />
<orderEntry type="module" module-name="intellij.platform.ide" />
<orderEntry type="module" module-name="intellij.platform.lang.impl" />
<orderEntry type="module" module-name="intellij.xml" />
<orderEntry type="module" module-name="intellij.spellchecker" />
<orderEntry type="library" name="Guava" level="project" />
<orderEntry type="library" name="gson" level="project" />
+17
View File
@@ -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<JsonValue> elements = ((JsonArray)parent).getValueList();
for (int i = 0; i < elements.size(); i++) {
if (e == elements.get(i)) {
return i;
}
}
return -1;
}
}
@@ -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<JsonValue> 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);
}
}
@@ -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<String> 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
@@ -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;
@@ -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<Crumb> caret = myFixture.getBreadcrumbsAtCaret();
assertOrderedEquals(caret.stream().map(Crumb::getText).toArray(String[]::new), components);
}
public void testComplexItems() {
doTest("foo", "bar", "0", "0", "baz");
}
}
@@ -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);
}
}
@@ -0,0 +1,11 @@
{
"foo": {
"bar": [
[
{
"baz<caret>": null
}
]
]
}
}