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.containers.SmartHashSet;
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;
36 public class ExtensionPointLocator {
37 private final PsiClass myPsiClass;
39 public ExtensionPointLocator(PsiClass psiClass) {
40 myPsiClass = psiClass;
44 public Set<ExtensionPointCandidate> findDirectCandidates() {
45 Set<ExtensionPointCandidate> candidates = new SmartHashSet<>();
46 findExtensionPointCandidates(myPsiClass, candidates);
50 public Set<ExtensionPointCandidate> findSuperCandidates() {
51 Set<ExtensionPointCandidate> candidates = new SmartHashSet<>();
52 findExtensionPointCandidatesInHierarchy(myPsiClass, candidates, new HashSet<>());
56 private static void findExtensionPointCandidatesInHierarchy(PsiClass psiClass,
57 Set<ExtensionPointCandidate> candidates,
58 HashSet<PsiClass> processed) {
59 for (PsiClass superClass : psiClass.getSupers()) {
60 if (!processed.add(superClass) || CommonClassNames.JAVA_LANG_OBJECT.equals(superClass.getQualifiedName())) {
63 findExtensionPointCandidates(superClass, candidates);
64 findExtensionPointCandidatesInHierarchy(superClass, candidates, processed);
68 private static void findExtensionPointCandidates(PsiClass psiClass, Set<ExtensionPointCandidate> candidates) {
69 String name = psiClass.getQualifiedName();
70 if (name == null) return;
72 Project project = psiClass.getProject();
73 GlobalSearchScope scope = PluginRelatedLocatorsUtils.getCandidatesScope(project);
74 PsiSearchHelper.SERVICE.getInstance(project).processUsagesInNonJavaFiles(name, (file, startOffset, endOffset) -> {
75 PsiElement element = file.findElementAt(startOffset);
76 processExtensionPointCandidate(element, candidates);
81 private static void processExtensionPointCandidate(PsiElement element, Set<ExtensionPointCandidate> candidates) {
82 XmlTag tag = PsiTreeUtil.getParentOfType(element, XmlTag.class);
83 if (tag == null) return;
84 if ("extensionPoint".equals(tag.getName())) {
85 String epName = getEPName(tag);
87 candidates.add(new ExtensionPointCandidate(SmartPointerManager.getInstance(tag.getProject()).createSmartPsiElementPointer(tag), epName));
90 else if ("with".equals(tag.getName())) {
91 XmlTag extensionPointTag = tag.getParentTag();
92 if (extensionPointTag == null) return;
93 if (!"extensionPoint".equals(extensionPointTag.getName())) return;
94 String attrName = tag.getAttributeValue("attribute");
95 String tagName = tag.getAttributeValue("tag");
96 String epName = getEPName(extensionPointTag);
97 String beanClassName = extensionPointTag.getAttributeValue("beanClass");
98 if ((attrName == null && tagName == null) || epName == null) return;
99 candidates.add(new ExtensionPointCandidate(SmartPointerManager.getInstance(extensionPointTag.getProject())
100 .createSmartPsiElementPointer(extensionPointTag), epName, attrName, tagName, beanClassName));
105 private static String getEPName(XmlTag tag) {
106 final DomElement domElement = DomUtil.getDomElement(tag);
107 if (!(domElement instanceof ExtensionPoint)) return null;
108 return ((ExtensionPoint)domElement).getEffectiveQualifiedName();