2 * Copyright 2000-2016 JetBrains s.r.o.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package org.jetbrains.idea.devkit.util;
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;
33 import java.util.HashSet;
34 import java.util.List;
36 public class ExtensionPointLocator {
38 private final PsiClass myPsiClass;
40 public ExtensionPointLocator(PsiClass psiClass) {
41 myPsiClass = psiClass;
44 public List<ExtensionPointCandidate> findDirectCandidates() {
45 final List<ExtensionPointCandidate> candidates = new SmartList<>();
46 findExtensionPointCandidates(myPsiClass, candidates);
50 public List<ExtensionPointCandidate> findSuperCandidates() {
51 final List<ExtensionPointCandidate> candidates = new SmartList<>();
52 findExtensionPointCandidatesInHierarchy(myPsiClass, candidates, new HashSet<>());
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())) {
64 findExtensionPointCandidates(superClass, list);
65 findExtensionPointCandidatesInHierarchy(superClass, list, processed);
69 private static void findExtensionPointCandidates(PsiClass psiClass, final List<ExtensionPointCandidate> list) {
70 String name = psiClass.getQualifiedName();
71 if (name == null) return;
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);
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);
88 list.add(new ExtensionPointCandidate(SmartPointerManager.getInstance(tag.getProject()).createSmartPsiElementPointer(tag), epName));
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));
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();