Skip to content

Commit 46451ef

Browse files
author
Vitaliy
authored
Merge pull request #97 from konarshankar07/graphql-codeinspection-resolver--task-35
#35: Inspection. GraphQL resolver should implement Resolver interface
2 parents 3ac6b7a + f3e15aa commit 46451ef

File tree

8 files changed

+164
-46
lines changed

8 files changed

+164
-46
lines changed

resources/META-INF/withJsGraphQl.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,11 @@
33
<fileBasedIndex implementation="com.magento.idea.magento2plugin.stubs.indexes.graphql.GraphQlResolverIndex" />
44
<codeInsight.lineMarkerProvider language="PHP" implementationClass="com.magento.idea.magento2plugin.php.linemarker.GraphQlResolverUsageLineMarkerProvider"/>
55
<codeInsight.lineMarkerProvider language="GraphQL" implementationClass="com.magento.idea.magento2plugin.graphql.linemarker.GraphQlResolverClassLineMarkerProvider"/>
6+
<localInspection language="PHP" groupPath="PHP"
7+
shortName="GraphQlResolverInspection" displayName="Graphql must implements ResolverInterface"
8+
groupName="Magento 2"
9+
enabledByDefault="true"
10+
level="ERROR"
11+
implementationClass="com.magento.idea.magento2plugin.inspections.php.GraphQlResolverInspection"/>
612
</extensions>
713
</idea-plugin>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!--
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
-->
7+
<html>
8+
<body>
9+
<p>
10+
All GraphQl resolver must implements Magento\Framework\GraphQl\Query\ResolverInterface interface
11+
</p>
12+
</body>
13+
</html>
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* Copyright © Magento, Inc. All rights reserved.
3+
* See COPYING.txt for license details.
4+
*/
5+
6+
package com.magento.idea.magento2plugin.inspections.php;
7+
8+
import com.intellij.codeInspection.ProblemHighlightType;
9+
import com.intellij.codeInspection.ProblemsHolder;
10+
import com.intellij.psi.PsiElement;
11+
import com.intellij.psi.PsiElementVisitor;
12+
import com.jetbrains.php.lang.inspections.PhpInspection;
13+
import com.jetbrains.php.lang.psi.elements.PhpClass;
14+
import com.jetbrains.php.lang.psi.visitors.PhpElementVisitor;
15+
import com.magento.idea.magento2plugin.inspections.php.fix.PhpImplementResolverClassQuickFix;
16+
import com.magento.idea.magento2plugin.util.magento.graphql.GraphQlUsagesCollector;
17+
import com.magento.idea.magento2plugin.util.magento.graphql.GraphQlUtil;
18+
import org.jetbrains.annotations.NotNull;
19+
20+
import java.util.List;
21+
22+
public class GraphQlResolverInspection extends PhpInspection {
23+
24+
public static final String GraphQlResolverProblemDescription = "Class must implements \\Magento\\Framework\\GraphQl\\Query\\ResolverInterface";
25+
26+
@NotNull
27+
@Override
28+
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder problemsHolder, boolean b) {
29+
return new PhpElementVisitor() {
30+
public void visitPhpClass(PhpClass resolverClass) {
31+
List<? extends PsiElement> results;
32+
GraphQlUsagesCollector collector = new GraphQlUsagesCollector();
33+
results = collector.getGraphQLUsages(resolverClass);
34+
if (results.size() > 0 ) {
35+
if (GraphQlUtil.isResolver(resolverClass)) {
36+
PsiElement currentClassNameIdentifier = resolverClass.getNameIdentifier();
37+
assert currentClassNameIdentifier != null;
38+
problemsHolder.registerProblem(currentClassNameIdentifier,
39+
GraphQlResolverProblemDescription,
40+
ProblemHighlightType.ERROR,
41+
new PhpImplementResolverClassQuickFix());
42+
}
43+
}
44+
}
45+
};
46+
}
47+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright © Magento, Inc. All rights reserved.
3+
* See COPYING.txt for license details.
4+
*/
5+
6+
package com.magento.idea.magento2plugin.inspections.php.fix;
7+
8+
import com.intellij.codeInspection.LocalQuickFix;
9+
import com.intellij.codeInspection.ProblemDescriptor;
10+
import com.intellij.openapi.project.Project;
11+
import com.intellij.psi.PsiElement;
12+
import com.jetbrains.php.lang.psi.PhpPsiElementFactory;
13+
import com.jetbrains.php.lang.psi.elements.PhpClass;
14+
import com.magento.idea.magento2plugin.magento.files.GraphQlResolver;
15+
import org.jetbrains.annotations.NotNull;
16+
17+
public class PhpImplementResolverClassQuickFix implements LocalQuickFix {
18+
@NotNull
19+
@Override
20+
public String getFamilyName() {
21+
return "Implements Resolver interface";
22+
}
23+
24+
@Override
25+
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
26+
PsiElement correctInterface = PhpPsiElementFactory.createImplementsList(project, GraphQlResolver.RESOLVER_INTERFACE);
27+
PhpClass graphQlResolverClass = (PhpClass) descriptor.getPsiElement().getParent();
28+
graphQlResolverClass.getImplementsList().replace(correctInterface);
29+
}
30+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/*
2+
* Copyright © Magento, Inc. All rights reserved.
3+
* See COPYING.txt for license details.
4+
*/
5+
package com.magento.idea.magento2plugin.magento.files;
6+
7+
public class GraphQlResolver {
8+
public static final String RESOLVER_INTERFACE = "\\Magento\\Framework\\GraphQl\\Query\\ResolverInterface";
9+
public static final String CLASS_ARGUMENT = "class";
10+
}

src/com/magento/idea/magento2plugin/php/linemarker/GraphQlResolverUsageLineMarkerProvider.java

Lines changed: 4 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,16 @@
88
import com.intellij.codeInsight.daemon.LineMarkerProvider;
99
import com.intellij.codeInsight.navigation.NavigationGutterIconBuilder;
1010
import com.intellij.lang.jsgraphql.GraphQLIcons;
11-
import com.intellij.lang.jsgraphql.psi.GraphQLQuotedString;
1211
import com.intellij.psi.PsiElement;
1312
import com.intellij.psi.util.PsiTreeUtil;
1413
import com.jetbrains.php.lang.psi.elements.PhpClass;
1514
import com.magento.idea.magento2plugin.project.Settings;
16-
import com.magento.idea.magento2plugin.stubs.indexes.graphql.GraphQlResolverIndex;
15+
import com.magento.idea.magento2plugin.util.magento.graphql.GraphQlUsagesCollector;
16+
import com.magento.idea.magento2plugin.util.magento.graphql.GraphQlUtil;
1717
import org.jetbrains.annotations.NotNull;
1818
import org.jetbrains.annotations.Nullable;
19-
import java.util.ArrayList;
19+
2020
import java.util.Collection;
21-
import java.util.HashMap;
2221
import java.util.List;
2322

2423
public class GraphQlResolverUsageLineMarkerProvider implements LineMarkerProvider {
@@ -40,7 +39,7 @@ public void collectSlowLineMarkers(@NotNull List<PsiElement> psiElements, @NotNu
4039
if (psiElement instanceof PhpClass) {
4140
List<? extends PsiElement> results;
4241

43-
if (!isResolver((PhpClass) psiElement)) {
42+
if (GraphQlUtil.isResolver((PhpClass) psiElement)) {
4443
return;
4544
}
4645
GraphQlUsagesCollector collector = new GraphQlUsagesCollector();
@@ -57,41 +56,4 @@ public void collectSlowLineMarkers(@NotNull List<PsiElement> psiElements, @NotNu
5756
}
5857
}
5958
}
60-
61-
private boolean isResolver(PhpClass psiElement) {
62-
PhpClass[] implementedInterfaces = psiElement.getImplementedInterfaces();
63-
for (PhpClass implementedInterface: implementedInterfaces) {
64-
if (!implementedInterface.getFQN().equals("\\Magento\\Framework\\GraphQl\\Query\\ResolverInterface")) {
65-
continue;
66-
}
67-
return true;
68-
}
69-
return false;
70-
}
71-
72-
private static class GraphQlUsagesCollector {
73-
74-
private HashMap<String, List<GraphQLQuotedString>> graphQlCache = new HashMap<>();
75-
76-
List<GraphQLQuotedString> getGraphQLUsages(@NotNull PhpClass phpClass) {
77-
List<GraphQLQuotedString> graphQLQuotedStrings = new ArrayList<>();
78-
79-
graphQLQuotedStrings.addAll(getUsages(phpClass));
80-
81-
return graphQLQuotedStrings;
82-
}
83-
84-
List<GraphQLQuotedString> getUsages(@NotNull PhpClass phpClass) {
85-
String phpClassFQN = phpClass.getFQN();
86-
if (!graphQlCache.containsKey(phpClassFQN)) {
87-
List<GraphQLQuotedString> graphQLStringValues = extractGraphQLQuotesStringsForClass(phpClass);
88-
graphQlCache.put(phpClassFQN, graphQLStringValues);
89-
}
90-
return graphQlCache.get(phpClassFQN);
91-
}
92-
93-
List<GraphQLQuotedString> extractGraphQLQuotesStringsForClass(@NotNull PhpClass phpClass) {
94-
return GraphQlResolverIndex.getGraphQLUsages(phpClass);
95-
}
96-
}
9759
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package com.magento.idea.magento2plugin.util.magento.graphql;
2+
3+
import com.intellij.lang.jsgraphql.psi.GraphQLQuotedString;
4+
import com.jetbrains.php.lang.psi.elements.PhpClass;
5+
import com.magento.idea.magento2plugin.stubs.indexes.graphql.GraphQlResolverIndex;
6+
import org.jetbrains.annotations.NotNull;
7+
8+
import java.util.ArrayList;
9+
import java.util.HashMap;
10+
import java.util.List;
11+
12+
public class GraphQlUsagesCollector {
13+
14+
public HashMap<String, List<GraphQLQuotedString>> graphQlCache = new HashMap<>();
15+
16+
public List<GraphQLQuotedString> getGraphQLUsages(@NotNull PhpClass phpClass) {
17+
List<GraphQLQuotedString> graphQLQuotedStrings = new ArrayList<>();
18+
19+
graphQLQuotedStrings.addAll(getUsages(phpClass));
20+
21+
return graphQLQuotedStrings;
22+
}
23+
24+
List<GraphQLQuotedString> getUsages(@NotNull PhpClass phpClass) {
25+
String phpClassFQN = phpClass.getFQN();
26+
if (!graphQlCache.containsKey(phpClassFQN)) {
27+
List<GraphQLQuotedString> graphQLStringValues = extractGraphQLQuotesStringsForClass(phpClass);
28+
graphQlCache.put(phpClassFQN, graphQLStringValues);
29+
}
30+
return graphQlCache.get(phpClassFQN);
31+
}
32+
33+
List<GraphQLQuotedString> extractGraphQLQuotesStringsForClass(@NotNull PhpClass phpClass) {
34+
return GraphQlResolverIndex.getGraphQLUsages(phpClass);
35+
}
36+
}

src/com/magento/idea/magento2plugin/util/magento/graphql/GraphQlUtil.java

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,19 @@
66

77
import com.intellij.lang.jsgraphql.psi.GraphQLStringValue;
88
import com.intellij.psi.PsiElement;
9+
import com.jetbrains.php.lang.psi.elements.PhpClass;
10+
import com.magento.idea.magento2plugin.magento.files.GraphQlResolver;
11+
import com.magento.idea.magento2plugin.magento.packages.Package;
912
import org.jetbrains.annotations.NotNull;
1013
import org.jetbrains.annotations.Nullable;
1114

1215
public class GraphQlUtil {
1316

1417
@NotNull
1518
public static String resolverStringToPhpFQN(String resolverFQN) {
16-
resolverFQN = resolverFQN.replace("\\\\", "\\").replace("\"","");
17-
if (!resolverFQN.startsWith("\\")) {
18-
resolverFQN = "\\".concat(resolverFQN);
19+
resolverFQN = resolverFQN.replace("\\\\", Package.FQN_SEPARATOR).replace("\"","");
20+
if (!resolverFQN.startsWith(Package.FQN_SEPARATOR)) {
21+
resolverFQN = Package.FQN_SEPARATOR.concat(resolverFQN);
1922
}
2023
return resolverFQN;
2124
}
@@ -34,10 +37,21 @@ public static GraphQLStringValue fetchResolverQuotedStringFromArgument(PsiElemen
3437

3538
GraphQLStringValue argumentStringValue = (GraphQLStringValue) argumentChildren[1];
3639

37-
if (!argumentIdentifier.getText().equals("class")) {
40+
if (!argumentIdentifier.getText().equals(GraphQlResolver.CLASS_ARGUMENT)) {
3841
return null;
3942
}
4043

4144
return argumentStringValue;
4245
}
46+
47+
public static boolean isResolver(PhpClass psiElement) {
48+
PhpClass[] implementedInterfaces = psiElement.getImplementedInterfaces();
49+
for (PhpClass implementedInterface: implementedInterfaces) {
50+
if (!implementedInterface.getFQN().equals(GraphQlResolver.RESOLVER_INTERFACE)) {
51+
continue;
52+
}
53+
return false;
54+
}
55+
return true;
56+
}
4357
}

0 commit comments

Comments
 (0)