Skip to content

Commit bc12022

Browse files
committed
A lot of shiny features and cleanup
[skip ci]
1 parent 0e26883 commit bc12022

38 files changed

+732
-748
lines changed

build.gradle.kts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,19 @@ spotless {
3939
kotlin {
4040
ktlint("0.43.2")
4141
}
42+
java {
43+
googleJavaFormat("1.13.0")
44+
}
45+
format("prettier") {
46+
target(
47+
"/*.md",
48+
"/*.yml",
49+
"/.github/**/*.yml",
50+
"/src/main/resources/META-INF/plugin.xml",
51+
"/src/main/resources/inspectionDescriptions/*.html"
52+
)
53+
prettier("2.5.1")
54+
}
4255
}
4356

4457
// https://github.com/JetBrains/gradle-intellij-plugin

gradle.properties

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
pluginGroup=nl.jrdie.idea.springql
2222
pluginName=spring-graphql-intellij-plugin
23-
pluginVersion=0.0.2-alpha.2
23+
pluginVersion=0.0.2-alpha.3
2424

2525
# See https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
2626
# for insight into build numbers and IntelliJ Platform versions.
@@ -29,15 +29,15 @@ pluginUntilBuild=213.*
2929

3030
# Plugin Verifier integration -> https://github.com/JetBrains/gradle-intellij-plugin#plugin-verifier-dsl
3131
# See https://jb.gg/intellij-platform-builds-list for available build versions.
32-
pluginVerifierIdeVersions=2020.3.4, 2021.1.3, 2021.3.1
32+
pluginVerifierIdeVersions=2021.1.3, 2021.3.1
3333

3434
platformType=IU
3535
platformVersion=IU-212.5457.46
3636
platformDownloadSources=true
3737

3838
# Plugin Dependencies -> https://plugins.jetbrains.com/docs/intellij/plugin-dependencies.html
3939
# Example: platformPlugins = com.intellij.java, com.jetbrains.php:203.4449.22
40-
platformPlugins=com.intellij.java, org.jetbrains.kotlin, IntelliLang, com.intellij.lang.jsgraphql:3.1.2, PsiViewer:212-SNAPSHOT
40+
platformPlugins=com.jetbrains.hackathon.indices.viewer:1.19, com.intellij.java, org.jetbrains.kotlin, IntelliLang, com.intellij.lang.jsgraphql:3.1.2, PsiViewer:212-SNAPSHOT
4141

4242
# Java language level used to compile sources and to generate the files for - Java 11 is required since 2020.3
4343
javaVersion=11
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package nl.jrdie.idea.springql.references;
2+
3+
import com.intellij.codeInsight.lookup.LookupElement;
4+
import com.intellij.codeInsight.lookup.LookupElementBuilder;
5+
import com.intellij.lang.jsgraphql.types.language.AbstractNode;
6+
import com.intellij.lang.jsgraphql.types.language.FieldDefinition;
7+
import com.intellij.lang.jsgraphql.types.schema.idl.TypeUtil;
8+
import com.intellij.psi.PsiElement;
9+
import com.intellij.psi.PsiElementResolveResult;
10+
import com.intellij.psi.PsiPolyVariantReferenceBase;
11+
import com.intellij.psi.ResolveResult;
12+
import com.intellij.util.ArrayUtilRt;
13+
import nl.jrdie.idea.springql.icons.QLIcons;
14+
import nl.jrdie.idea.springql.svc.QLIdeService;
15+
import nl.jrdie.idea.springql.types.SchemaMappingSummary;
16+
import org.jetbrains.annotations.NotNull;
17+
import org.jetbrains.uast.UMethod;
18+
import org.jetbrains.uast.UastContextKt;
19+
20+
import java.util.Objects;
21+
22+
public class QLArgumentNamePolyReference extends PsiPolyVariantReferenceBase<PsiElement> {
23+
24+
public QLArgumentNamePolyReference(@NotNull PsiElement psiElement) {
25+
super(Objects.requireNonNull(psiElement, "element"));
26+
}
27+
28+
@NotNull
29+
@Override
30+
public Object[] getVariants() {
31+
final UMethod uMethod = UastContextKt.getUastParentOfType(myElement, UMethod.class);
32+
if (uMethod == null) {
33+
return ArrayUtilRt.EMPTY_OBJECT_ARRAY;
34+
}
35+
36+
final QLIdeService svc = myElement.getProject().getService(QLIdeService.class);
37+
final SchemaMappingSummary summary = svc.getSummaryForMethod(uMethod);
38+
if (summary == null) {
39+
return ArrayUtilRt.EMPTY_OBJECT_ARRAY;
40+
}
41+
42+
final FieldDefinition fieldDefinition = svc.getSchemaRegistry()
43+
.getFieldDefinition(summary.getTypeName(), summary.getFieldName());
44+
if (fieldDefinition == null) {
45+
return ArrayUtilRt.EMPTY_OBJECT_ARRAY;
46+
}
47+
48+
return fieldDefinition
49+
.getInputValueDefinitions()
50+
.stream()
51+
.map(input -> LookupElementBuilder.create(input.getName())
52+
.withTypeText(TypeUtil.simplePrint(input.getType()))
53+
.withPsiElement(input.getElement())
54+
.withIcon(QLIcons.INSTANCE.getVariable()))
55+
.toArray(LookupElement[]::new);
56+
}
57+
58+
@NotNull
59+
@Override
60+
public ResolveResult[] multiResolve(boolean incompleteCode) {
61+
final UMethod uMethod = UastContextKt.getUastParentOfType(myElement, UMethod.class);
62+
if (uMethod == null) {
63+
return ResolveResult.EMPTY_ARRAY;
64+
}
65+
66+
final QLIdeService svc = myElement.getProject().getService(QLIdeService.class);
67+
final SchemaMappingSummary summary = svc.getSummaryForMethod(uMethod);
68+
if (summary == null) {
69+
return ResolveResult.EMPTY_ARRAY;
70+
}
71+
72+
final FieldDefinition fieldDefinition = svc.getSchemaRegistry()
73+
.getFieldDefinition(summary.getTypeName(), summary.getFieldName());
74+
if (fieldDefinition == null) {
75+
return ResolveResult.EMPTY_ARRAY;
76+
}
77+
78+
return fieldDefinition
79+
.getInputValueDefinitions()
80+
.stream()
81+
.map(AbstractNode::getElement)
82+
.filter(Objects::nonNull)
83+
.map(PsiElementResolveResult::new)
84+
.toArray(ResolveResult[]::new);
85+
}
86+
}
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
package nl.jrdie.idea.springql.references;
2+
3+
import com.intellij.codeInsight.completion.PrioritizedLookupElement;
4+
import com.intellij.codeInsight.lookup.LookupElement;
5+
import com.intellij.codeInsight.lookup.LookupElementBuilder;
6+
import com.intellij.lang.jsgraphql.types.language.FieldDefinition;
7+
import com.intellij.lang.jsgraphql.types.language.ObjectTypeDefinition;
8+
import com.intellij.psi.PsiElement;
9+
import com.intellij.psi.PsiElementResolveResult;
10+
import com.intellij.psi.PsiPolyVariantReferenceBase;
11+
import com.intellij.psi.ResolveResult;
12+
import nl.jrdie.idea.springql.icons.QLIcons;
13+
import nl.jrdie.idea.springql.index.entry.SchemaMappingIndexEntry;
14+
import nl.jrdie.idea.springql.svc.QLIdeService;
15+
import nl.jrdie.idea.springql.utils.QLIdeUtil;
16+
import org.jetbrains.annotations.NotNull;
17+
import org.jetbrains.annotations.Nullable;
18+
import org.jetbrains.uast.UAnnotation;
19+
import org.jetbrains.uast.UMethod;
20+
import org.jetbrains.uast.UastContextKt;
21+
22+
import javax.swing.Icon;
23+
import java.util.List;
24+
import java.util.Objects;
25+
import java.util.Set;
26+
27+
public class QLFieldPolyReference extends PsiPolyVariantReferenceBase<PsiElement> {
28+
29+
public QLFieldPolyReference(@NotNull PsiElement psiElement) {
30+
super(Objects.requireNonNull(psiElement, "psiElement"));
31+
}
32+
33+
@NotNull
34+
@Override
35+
public ResolveResult[] multiResolve(boolean incompleteCode) {
36+
final QLIdeService svc = myElement.getProject().getService(QLIdeService.class);
37+
if (!svc.isApplicableProject(myElement.getProject())) {
38+
return ResolveResult.EMPTY_ARRAY;
39+
}
40+
41+
final UAnnotation parentAnnotation = UastContextKt.getUastParentOfType(myElement, UAnnotation.class);
42+
if (parentAnnotation == null) {
43+
return ResolveResult.EMPTY_ARRAY;
44+
}
45+
46+
final Set<SchemaMappingIndexEntry> annotations = svc.getIndex().schemaMappingByAnnotation(parentAnnotation);
47+
48+
return annotations
49+
.stream()
50+
.map(SchemaMappingIndexEntry::getSchemaPsi)
51+
.flatMap(List::stream)
52+
.map(PsiElementResolveResult::new)
53+
.toArray(ResolveResult[]::new);
54+
}
55+
56+
@NotNull
57+
@Override
58+
public Object[] getVariants() {
59+
final QLIdeService svc = myElement.getProject().getService(QLIdeService.class);
60+
61+
return svc
62+
.getSchemaRegistry()
63+
.getFieldDefinitions()
64+
.stream()
65+
.map(fieldDefinition -> createLookupElement(svc, fieldDefinition))
66+
.filter(Objects::nonNull)
67+
.toArray(LookupElement[]::new);
68+
}
69+
70+
@Nullable
71+
private LookupElement createLookupElement(@NotNull QLIdeService svc,
72+
@NotNull FieldDefinition fieldDefinition) {
73+
Objects.requireNonNull(svc, "svc");
74+
Objects.requireNonNull(fieldDefinition, "fieldDefinition");
75+
76+
final PsiElement targetElement = fieldDefinition.getElement();
77+
if (targetElement == null) {
78+
return null;
79+
}
80+
81+
final UAnnotation nearestAnnotation = svc.findNearestSchemaMappingAnnotations(UastContextKt.toUElement(myElement))
82+
.stream()
83+
.findFirst()
84+
.orElse(null);
85+
86+
ObjectTypeDefinition parentTypeByAnnotation = null;
87+
if (nearestAnnotation != null) {
88+
final String parentTypeName = svc.findApplicableParentTypeName(nearestAnnotation);
89+
if (parentTypeName == null) {
90+
return null;
91+
}
92+
93+
parentTypeByAnnotation = svc.getSchemaRegistry().getObjectTypeDefinition(parentTypeName);
94+
}
95+
96+
final boolean isChildOfCurrentAnnotationParentType = parentTypeByAnnotation != null &&
97+
parentTypeByAnnotation
98+
.getFieldDefinitions()
99+
.contains(fieldDefinition);
100+
101+
String correctDisplayName = null;
102+
if (isChildOfCurrentAnnotationParentType) {
103+
correctDisplayName = fieldDefinition.getName();
104+
} else {
105+
final ObjectTypeDefinition parentTypeDefinition = svc.getSchemaRegistry().getParentType(fieldDefinition);
106+
if (parentTypeDefinition != null) {
107+
correctDisplayName = parentTypeDefinition.getName() + ".";
108+
}
109+
correctDisplayName += fieldDefinition.getName();
110+
}
111+
112+
final String typeText = QLIdeUtil.printTypeVal(fieldDefinition.getType());
113+
114+
final Icon icon = getLookupIcon(svc, fieldDefinition);
115+
116+
final LookupElement intermediateLookupElement = LookupElementBuilder
117+
.create(fieldDefinition.getName())
118+
.withPresentableText(correctDisplayName)
119+
.withPsiElement(fieldDefinition.getElement())
120+
.withIcon(icon)
121+
.withBoldness(isChildOfCurrentAnnotationParentType)
122+
.withStrikeoutness(fieldDefinition.hasDirective("deprecated"))
123+
.withTypeText(typeText);
124+
125+
return PrioritizedLookupElement
126+
.withPriority(intermediateLookupElement, determinePriority(fieldDefinition, parentTypeByAnnotation, svc));
127+
}
128+
129+
private Icon getLookupIcon(@NotNull QLIdeService svc,
130+
@NotNull FieldDefinition fieldDefinition) {
131+
Objects.requireNonNull(svc, "svc");
132+
Objects.requireNonNull(fieldDefinition, "fieldDefinition");
133+
134+
if (svc.isApolloFederationNode(fieldDefinition)) {
135+
return QLIcons.INSTANCE.getApollo();
136+
}
137+
if (svc.isIntrospectionNode(fieldDefinition)) {
138+
return QLIcons.INSTANCE.getIntrospectionFieldType();
139+
}
140+
return QLIcons.INSTANCE.getField();
141+
}
142+
143+
private double determinePriority(@NotNull FieldDefinition fieldDefinition,
144+
@Nullable ObjectTypeDefinition parentType,
145+
@NotNull QLIdeService svc) {
146+
Objects.requireNonNull(fieldDefinition, "fieldDefinition");
147+
Objects.requireNonNull(svc, "svc");
148+
149+
if (svc.isIntrospectionNode(fieldDefinition)) {
150+
return 0.0;
151+
}
152+
153+
if (fieldDefinition.hasDirective("deprecated")) {
154+
return 7.0;
155+
}
156+
157+
UMethod nearestMethod = UastContextKt.getUastParentOfType(myElement, UMethod.class);
158+
if (nearestMethod != null) {
159+
if (fieldDefinition.getName().equalsIgnoreCase(nearestMethod.getName())) {
160+
return 10.0;
161+
}
162+
}
163+
164+
if (parentType != null && parentType.getFieldDefinitions().contains(fieldDefinition)) {
165+
return 8.0;
166+
}
167+
168+
return 5.0;
169+
}
170+
171+
}

0 commit comments

Comments
 (0)