blob: c4a5b19c156a6b5dc9583af545584acc5cecd766 [file] [log] [blame]
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.idea.devkit.util;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PsiNonJavaFileReferenceProcessor;
import com.intellij.psi.search.PsiSearchHelper;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.SmartList;
import com.intellij.util.xml.DomElement;
import com.intellij.util.xml.DomService;
import com.intellij.util.xml.DomUtil;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.devkit.dom.ExtensionPoint;
import org.jetbrains.idea.devkit.dom.IdeaPlugin;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
public class ExtensionPointLocator {
private final PsiClass myPsiClass;
public ExtensionPointLocator(PsiClass psiClass) {
myPsiClass = psiClass;
}
public List<ExtensionPointCandidate> findDirectCandidates() {
final List<ExtensionPointCandidate> candidates = new SmartList<ExtensionPointCandidate>();
findExtensionPointCandidates(myPsiClass, candidates);
return candidates;
}
public List<ExtensionPointCandidate> findSuperCandidates() {
final List<ExtensionPointCandidate> candidates = new SmartList<ExtensionPointCandidate>();
findExtensionPointCandidatesInHierarchy(myPsiClass, candidates, new HashSet<PsiClass>());
return candidates;
}
private static void findExtensionPointCandidatesInHierarchy(PsiClass psiClass,
List<ExtensionPointCandidate> list,
HashSet<PsiClass> processed) {
for (PsiClass superClass : psiClass.getSupers()) {
if (!processed.add(superClass) ||
CommonClassNames.JAVA_LANG_OBJECT.equals(superClass.getQualifiedName())) {
continue;
}
findExtensionPointCandidates(superClass, list);
findExtensionPointCandidatesInHierarchy(superClass, list, processed);
}
}
private static void findExtensionPointCandidates(PsiClass psiClass, final List<ExtensionPointCandidate> list) {
String name = psiClass.getQualifiedName();
if (name == null) {
return;
}
final Project project = psiClass.getProject();
final Collection<VirtualFile> candidates = DomService.getInstance().getDomFileCandidates(IdeaPlugin.class, project);
GlobalSearchScope scope = GlobalSearchScope.filesScope(project, candidates);
PsiSearchHelper.SERVICE.getInstance(project).processUsagesInNonJavaFiles(name, new PsiNonJavaFileReferenceProcessor() {
@Override
public boolean process(PsiFile file, int startOffset, int endOffset) {
PsiElement element = file.findElementAt(startOffset);
processExtensionPointCandidate(element, list);
return true;
}
}, scope);
}
private static void processExtensionPointCandidate(PsiElement element, List<ExtensionPointCandidate> list) {
XmlTag tag = PsiTreeUtil.getParentOfType(element, XmlTag.class);
if (tag == null) return;
if ("extensionPoint".equals(tag.getName())) {
String epName = getEPName(tag);
if (epName != null) {
list.add(new ExtensionPointCandidate(createPointer(tag), epName));
}
}
else if ("with".equals(tag.getName())) {
XmlTag extensionPointTag = tag.getParentTag();
if (extensionPointTag == null) return;
if (!"extensionPoint".equals(extensionPointTag.getName())) return;
String attrName = tag.getAttributeValue("attribute");
String tagName = tag.getAttributeValue("tag");
String epName = getEPName(extensionPointTag);
String beanClassName = extensionPointTag.getAttributeValue("beanClass");
if ((attrName == null && tagName == null) || epName == null) return;
list.add(new ExtensionPointCandidate(createPointer(extensionPointTag), epName, attrName, tagName, beanClassName));
}
}
private static SmartPsiElementPointer createPointer(XmlTag extensionPointTag) {
return SmartPointerManager.getInstance(extensionPointTag.getProject()).createSmartPsiElementPointer(extensionPointTag);
}
@Nullable
private static String getEPName(XmlTag tag) {
final DomElement domElement = DomUtil.getDomElement(tag);
if (!(domElement instanceof ExtensionPoint)) return null;
return ((ExtensionPoint)domElement).getEffectiveQualifiedName();
}
}