Skip to content

Commit 6061963

Browse files
authored
Merge pull request #897 from bohdan-harniuk/654-fix-ClassCastException-in-WebApiTypeIndex
654: fixed class cast exception in web api type index
2 parents b4fcdce + ba99c90 commit 6061963

File tree

1 file changed

+96
-55
lines changed

1 file changed

+96
-55
lines changed

src/com/magento/idea/magento2plugin/stubs/indexes/WebApiTypeIndex.java

Lines changed: 96 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
/**
1+
/*
22
* Copyright © Magento, Inc. All rights reserved.
33
* See COPYING.txt for license details.
44
*/
5+
56
package com.magento.idea.magento2plugin.stubs.indexes;
67

78
import com.intellij.ide.highlighter.XmlFileType;
@@ -13,88 +14,97 @@
1314
import com.intellij.psi.xml.XmlDocument;
1415
import com.intellij.psi.xml.XmlFile;
1516
import com.intellij.psi.xml.XmlTag;
16-
import com.intellij.util.indexing.*;
17+
import com.intellij.util.indexing.DataIndexer;
18+
import com.intellij.util.indexing.FileBasedIndex;
19+
import com.intellij.util.indexing.FileContent;
20+
import com.intellij.util.indexing.ID;
21+
import com.intellij.util.indexing.ScalarIndexExtension;
1722
import com.intellij.util.io.EnumeratorStringDescriptor;
1823
import com.intellij.util.io.KeyDescriptor;
1924
import com.jetbrains.php.lang.PhpLangUtil;
2025
import com.jetbrains.php.lang.psi.elements.Method;
2126
import com.jetbrains.php.lang.psi.elements.PhpClass;
22-
import com.magento.idea.magento2plugin.project.Settings;
2327
import com.magento.idea.magento2plugin.linemarker.xml.LineMarkerXmlTagDecorator;
28+
import com.magento.idea.magento2plugin.project.Settings;
29+
import java.util.ArrayList;
30+
import java.util.Collection;
31+
import java.util.HashMap;
32+
import java.util.List;
33+
import java.util.Map;
2434
import org.jetbrains.annotations.NonNls;
2535
import org.jetbrains.annotations.NotNull;
2636

27-
import java.util.*;
28-
2937
/**
3038
* Indexer for classes/interfaces which have methods exposed via Web API.
3139
*/
3240
public class WebApiTypeIndex extends ScalarIndexExtension<String> {
3341

34-
public static final ID<String, Void> KEY = ID.create("com.magento.idea.magento2plugin.stubs.indexes.webapi_type");
35-
42+
public static final ID<String, Void> KEY = ID.create(
43+
"com.magento.idea.magento2plugin.stubs.indexes.webapi_type"
44+
);
3645
private final KeyDescriptor<String> keyDescriptor = new EnumeratorStringDescriptor();
3746

38-
@NotNull
3947
@Override
40-
public ID<String, Void> getName() {
48+
public @NotNull ID<String, Void> getName() {
4149
return KEY;
4250
}
4351

44-
@NotNull
52+
@SuppressWarnings("PMD.CognitiveComplexity")
4553
@Override
46-
public DataIndexer<String, Void, FileContent> getIndexer() {
54+
public @NotNull DataIndexer<String, Void, FileContent> getIndexer() {
4755
return inputData -> {
48-
Map<String, Void> map = new HashMap<>();
56+
final Map<String, Void> map = new HashMap<>();
57+
final PsiFile psiFile = inputData.getPsiFile();
4958

50-
PsiFile psiFile = inputData.getPsiFile();
5159
if (!Settings.isEnabled(psiFile.getProject())) {
5260
return map;
5361
}
5462

5563
if (!(psiFile instanceof XmlFile)) {
5664
return map;
5765
}
66+
final XmlDocument document = ((XmlFile) psiFile).getDocument();
5867

59-
XmlDocument document = ((XmlFile) psiFile).getDocument();
6068
if (document == null) {
6169
return map;
6270
}
71+
final XmlTag[] xmlTags = PsiTreeUtil.getChildrenOfType(
72+
psiFile.getFirstChild(),
73+
XmlTag.class
74+
);
6375

64-
XmlTag xmlTags[] = PsiTreeUtil.getChildrenOfType(psiFile.getFirstChild(), XmlTag.class);
6576
if (xmlTags == null) {
6677
return map;
6778
}
6879

69-
for (XmlTag xmlTag : xmlTags) {
70-
if (xmlTag.getName().equals("routes")) {
71-
for (XmlTag routeNode : xmlTag.findSubTags("route")) {
72-
for (XmlTag serviceNode : routeNode.findSubTags("service")) {
73-
String typeName = serviceNode.getAttributeValue("class");
80+
for (final XmlTag xmlTag : xmlTags) {
81+
if ("routes".equals(xmlTag.getName())) {
82+
for (final XmlTag routeNode : xmlTag.findSubTags("route")) {
83+
for (final XmlTag serviceNode : routeNode.findSubTags("service")) {
84+
final String typeName = serviceNode.getAttributeValue("class");
85+
7486
if (typeName != null) {
7587
map.put(PhpLangUtil.toPresentableFQN(typeName), null);
7688
}
7789
}
7890
}
7991
}
8092
}
93+
8194
return map;
8295
};
8396
}
8497

85-
@NotNull
8698
@Override
87-
public KeyDescriptor<String> getKeyDescriptor() {
99+
public @NotNull KeyDescriptor<String> getKeyDescriptor() {
88100
return keyDescriptor;
89101
}
90102

91-
@NotNull
92103
@Override
93-
public FileBasedIndex.InputFilter getInputFilter() {
94-
return file -> (
95-
file.getFileType() == XmlFileType.INSTANCE && file.getNameWithoutExtension().equals("webapi")
96-
&& !file.getPath().contains("testsuite") && !file.getPath().contains("_files")
97-
);
104+
public @NotNull FileBasedIndex.InputFilter getInputFilter() {
105+
return file -> file.getFileType() == XmlFileType.INSTANCE
106+
&& "webapi".equals(file.getNameWithoutExtension())
107+
&& !file.getPath().contains("testsuite") && !file.getPath().contains("_files");
98108
}
99109

100110
@Override
@@ -109,45 +119,77 @@ public int getVersion() {
109119

110120
/**
111121
* Get list of Web API routes associated with the provided method.
112-
*
113122
* Parent classes are not taken into account.
123+
*
124+
* @param method Method
125+
*
126+
* @return List[XmlTag]
114127
*/
115-
public static List<XmlTag> getWebApiRoutes(Method method) {
116-
List<XmlTag> tags = new ArrayList<>();
128+
public static List<XmlTag> getWebApiRoutes(final Method method) {
129+
final List<XmlTag> tags = new ArrayList<>();
130+
117131
if (!method.getAccess().isPublic()) {
118132
return tags;
119133
}
120-
PhpClass phpClass = method.getContainingClass();
121-
String methodFqn = method.getName();
134+
final PhpClass phpClass = method.getContainingClass();
135+
122136
if (phpClass == null) {
123137
return tags;
124138
}
125-
String classFqn = phpClass.getPresentableFQN();
126-
Collection<VirtualFile> containingFiles = FileBasedIndex
127-
.getInstance().getContainingFiles(KEY, classFqn, GlobalSearchScope.allScope(phpClass.getProject()));
139+
final String classFqn = phpClass.getPresentableFQN();
140+
final Collection<VirtualFile> containingFiles = FileBasedIndex
141+
.getInstance()
142+
.getContainingFiles(
143+
KEY,
144+
classFqn,
145+
GlobalSearchScope.allScope(phpClass.getProject())
146+
);
147+
148+
final PsiManager psiManager = PsiManager.getInstance(phpClass.getProject());
149+
final String methodFqn = method.getName();
150+
151+
for (final VirtualFile virtualFile : containingFiles) {
152+
if (virtualFile.getFileType() != XmlFileType.INSTANCE) {
153+
continue;
154+
}
155+
final XmlFile file = (XmlFile) psiManager.findFile(virtualFile);
128156

129-
PsiManager psiManager = PsiManager.getInstance(phpClass.getProject());
130-
for (VirtualFile virtualFile : containingFiles) {
131-
XmlFile file = (XmlFile) psiManager.findFile(virtualFile);
132157
if (file == null) {
133158
continue;
134159
}
135-
XmlTag rootTag = file.getRootTag();
160+
final XmlTag rootTag = file.getRootTag();
161+
162+
if (rootTag == null) {
163+
continue;
164+
}
136165
fillRelatedTags(classFqn, methodFqn, rootTag, tags);
137166
}
167+
138168
return tags;
139169
}
140170

141171
/**
142-
* Find routes related to the specified method within single webapi.xml
172+
* Find routes related to the specified method within single webapi.xml.
173+
*
174+
* @param classFqn String
175+
* @param methodFqn String
176+
* @param parentTag XmlTag
177+
* @param tagsReferences List[XmlTag]
143178
*/
144-
private static void fillRelatedTags(String classFqn, String methodFqn, XmlTag parentTag, List<XmlTag> tagsReferences) {
145-
for (XmlTag routeNode : parentTag.findSubTags("route")) {
146-
for (XmlTag serviceNode : routeNode.findSubTags("service")) {
147-
String typeName = serviceNode.getAttributeValue("class");
148-
String methodName = serviceNode.getAttributeValue("method");
179+
@SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops")
180+
private static void fillRelatedTags(
181+
final String classFqn,
182+
final String methodFqn,
183+
final XmlTag parentTag,
184+
final List<XmlTag> tagsReferences
185+
) {
186+
for (final XmlTag routeNode : parentTag.findSubTags("route")) {
187+
for (final XmlTag serviceNode : routeNode.findSubTags("service")) {
188+
final String typeName = serviceNode.getAttributeValue("class");
189+
final String methodName = serviceNode.getAttributeValue("method");
190+
149191
if (typeName != null && typeName.equals(classFqn)
150-
&& methodName != null && methodName.equals(methodFqn)
192+
&& methodName != null && methodName.equals(methodFqn)
151193
) {
152194
tagsReferences.add(new WebApiLineMarkerXmlTagDecorator(routeNode));
153195
}
@@ -160,25 +202,24 @@ private static void fillRelatedTags(String classFqn, String methodFqn, XmlTag pa
160202
*/
161203
private static class WebApiLineMarkerXmlTagDecorator extends LineMarkerXmlTagDecorator {
162204

163-
WebApiLineMarkerXmlTagDecorator(XmlTag xmlTag) {
205+
public WebApiLineMarkerXmlTagDecorator(final XmlTag xmlTag) {
164206
super(xmlTag);
165207
}
166208

167-
@NotNull
168209
@Override
169-
public String getDescription() {
210+
public @NotNull String getDescription() {
170211
return "";
171212
}
172213

173214
@Override
174-
@NotNull
175-
@NonNls
176-
public String getName() {
177-
String httpMethod = this.xmlTag.getAttributeValue("method");
178-
String route = this.xmlTag.getAttributeValue("url");
215+
public @NonNls @NotNull String getName() {
216+
final String httpMethod = this.xmlTag.getAttributeValue("method");
217+
final String route = this.xmlTag.getAttributeValue("url");
218+
179219
if (httpMethod != null && route != null) {
180220
return String.format(" %-7s %s", httpMethod, route);
181221
}
222+
182223
return xmlTag.getName();
183224
}
184225
}

0 commit comments

Comments
 (0)