don't search for custom engine if junit 5 is not on classpath
[idea/community.git] / plugins / devkit / src / util / ExtensionPointLocator.java
1 /*
2  * Copyright 2000-2016 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package org.jetbrains.idea.devkit.util;
17
18 import com.intellij.openapi.project.Project;
19 import com.intellij.psi.CommonClassNames;
20 import com.intellij.psi.PsiClass;
21 import com.intellij.psi.PsiElement;
22 import com.intellij.psi.SmartPointerManager;
23 import com.intellij.psi.search.GlobalSearchScope;
24 import com.intellij.psi.search.PsiSearchHelper;
25 import com.intellij.psi.util.PsiTreeUtil;
26 import com.intellij.psi.xml.XmlTag;
27 import com.intellij.util.SmartList;
28 import com.intellij.util.xml.DomElement;
29 import com.intellij.util.xml.DomUtil;
30 import org.jetbrains.annotations.Nullable;
31 import org.jetbrains.idea.devkit.dom.ExtensionPoint;
32
33 import java.util.HashSet;
34 import java.util.List;
35
36 public class ExtensionPointLocator {
37
38   private final PsiClass myPsiClass;
39
40   public ExtensionPointLocator(PsiClass psiClass) {
41     myPsiClass = psiClass;
42   }
43
44   public List<ExtensionPointCandidate> findDirectCandidates() {
45     final List<ExtensionPointCandidate> candidates = new SmartList<>();
46     findExtensionPointCandidates(myPsiClass, candidates);
47     return candidates;
48   }
49
50   public List<ExtensionPointCandidate> findSuperCandidates() {
51     final List<ExtensionPointCandidate> candidates = new SmartList<>();
52     findExtensionPointCandidatesInHierarchy(myPsiClass, candidates, new HashSet<>());
53     return candidates;
54   }
55
56   private static void findExtensionPointCandidatesInHierarchy(PsiClass psiClass,
57                                                               List<ExtensionPointCandidate> list,
58                                                               HashSet<PsiClass> processed) {
59     for (PsiClass superClass : psiClass.getSupers()) {
60       if (!processed.add(superClass) ||
61           CommonClassNames.JAVA_LANG_OBJECT.equals(superClass.getQualifiedName())) {
62         continue;
63       }
64       findExtensionPointCandidates(superClass, list);
65       findExtensionPointCandidatesInHierarchy(superClass, list, processed);
66     }
67   }
68
69   private static void findExtensionPointCandidates(PsiClass psiClass, final List<ExtensionPointCandidate> list) {
70     String name = psiClass.getQualifiedName();
71     if (name == null) return;
72
73     Project project = psiClass.getProject();
74     GlobalSearchScope scope = PluginRelatedLocatorsUtils.getCandidatesScope(project);
75     PsiSearchHelper.SERVICE.getInstance(project).processUsagesInNonJavaFiles(name, (file, startOffset, endOffset) -> {
76       PsiElement element = file.findElementAt(startOffset);
77       processExtensionPointCandidate(element, list);
78       return true;
79     }, scope);
80   }
81
82   private static void processExtensionPointCandidate(PsiElement element, List<ExtensionPointCandidate> list) {
83     XmlTag tag = PsiTreeUtil.getParentOfType(element, XmlTag.class);
84     if (tag == null) return;
85     if ("extensionPoint".equals(tag.getName())) {
86       String epName = getEPName(tag);
87       if (epName != null) {
88         list.add(new ExtensionPointCandidate(SmartPointerManager.getInstance(tag.getProject()).createSmartPsiElementPointer(tag), epName));
89       }
90     }
91     else if ("with".equals(tag.getName())) {
92       XmlTag extensionPointTag = tag.getParentTag();
93       if (extensionPointTag == null) return;
94       if (!"extensionPoint".equals(extensionPointTag.getName())) return;
95       String attrName = tag.getAttributeValue("attribute");
96       String tagName = tag.getAttributeValue("tag");
97       String epName = getEPName(extensionPointTag);
98       String beanClassName = extensionPointTag.getAttributeValue("beanClass");
99       if ((attrName == null && tagName == null) || epName == null) return;
100       list.add(new ExtensionPointCandidate(SmartPointerManager.getInstance(extensionPointTag.getProject())
101                                              .createSmartPsiElementPointer(extensionPointTag), epName, attrName, tagName, beanClassName));
102     }
103   }
104
105   @Nullable
106   private static String getEPName(XmlTag tag) {
107     final DomElement domElement = DomUtil.getDomElement(tag);
108     if (!(domElement instanceof ExtensionPoint)) return null;
109     return ((ExtensionPoint)domElement).getEffectiveQualifiedName();
110   }
111 }