blob: 551fd38b9dc2d1daa7ff1e2e83f81eb88af40c61 [file] [log] [blame]
/*
* Copyright 2000-2013 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 com.intellij.ide.hierarchy;
import com.intellij.ide.util.treeView.AbstractTreeStructure;
import com.intellij.ide.util.treeView.NodeDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.search.*;
import com.intellij.psi.search.scope.packageSet.NamedScope;
import com.intellij.psi.search.scope.packageSet.NamedScopeManager;
import com.intellij.psi.search.scope.packageSet.NamedScopesHolder;
import com.intellij.psi.search.scope.packageSet.PackageSet;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.ui.JBColor;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
public abstract class HierarchyTreeStructure extends AbstractTreeStructure {
protected HierarchyNodeDescriptor myBaseDescriptor;
private HierarchyNodeDescriptor myRoot;
@NotNull
protected final Project myProject;
protected HierarchyTreeStructure(@NotNull Project project, HierarchyNodeDescriptor baseDescriptor) {
myBaseDescriptor = baseDescriptor;
myProject = project;
myRoot = baseDescriptor;
}
public final HierarchyNodeDescriptor getBaseDescriptor() {
return myBaseDescriptor;
}
protected final void setBaseElement(@NotNull HierarchyNodeDescriptor baseElement) {
myBaseDescriptor = baseElement;
myRoot = baseElement;
while(myRoot.getParentDescriptor() != null){
myRoot = (HierarchyNodeDescriptor)myRoot.getParentDescriptor();
}
}
@Override
@NotNull
public final NodeDescriptor createDescriptor(final Object element, final NodeDescriptor parentDescriptor) {
if (element instanceof HierarchyNodeDescriptor) {
return (HierarchyNodeDescriptor)element;
}
if (element instanceof String) {
return new TextInfoNodeDescriptor(parentDescriptor, (String)element, myProject);
}
throw new IllegalArgumentException("Unknown element type: " + element);
}
@Override
public final boolean isToBuildChildrenInBackground(final Object element) {
if (element instanceof HierarchyNodeDescriptor){
final HierarchyNodeDescriptor descriptor = (HierarchyNodeDescriptor)element;
final Object[] cachedChildren = descriptor.getCachedChildren();
if (cachedChildren == null && descriptor.isValid()){
return true;
}
}
return false;
}
@Override
public final Object[] getChildElements(final Object element) {
if (element instanceof HierarchyNodeDescriptor) {
final HierarchyNodeDescriptor descriptor = (HierarchyNodeDescriptor)element;
final Object[] cachedChildren = descriptor.getCachedChildren();
if (cachedChildren == null) {
if (descriptor.isValid()) {
descriptor.setCachedChildren(buildChildren(descriptor));
}
else {
descriptor.setCachedChildren(ArrayUtil.EMPTY_OBJECT_ARRAY);
}
}
return descriptor.getCachedChildren();
}
return ArrayUtil.EMPTY_OBJECT_ARRAY;
}
@Override
public final Object getParentElement(final Object element) {
if (element instanceof HierarchyNodeDescriptor) {
return ((HierarchyNodeDescriptor)element).getParentDescriptor();
}
return null;
}
@Override
public final void commit() {
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
}
@Override
public final boolean hasSomethingToCommit() {
return PsiDocumentManager.getInstance(myProject).hasUncommitedDocuments();
}
@NotNull
@Override
public ActionCallback asyncCommit() {
return asyncCommitDocuments(myProject);
}
@NotNull
protected abstract Object[] buildChildren(@NotNull HierarchyNodeDescriptor descriptor);
@Override
public final Object getRootElement() {
return myRoot;
}
protected SearchScope getSearchScope(final String scopeType, final PsiElement thisClass) {
SearchScope searchScope = GlobalSearchScope.allScope(myProject);
if (HierarchyBrowserBaseEx.SCOPE_CLASS.equals(scopeType)) {
searchScope = new LocalSearchScope(thisClass);
}
else if (HierarchyBrowserBaseEx.SCOPE_PROJECT.equals(scopeType)) {
searchScope = GlobalSearchScopesCore.projectProductionScope(myProject);
}
else if (HierarchyBrowserBaseEx.SCOPE_TEST.equals(scopeType)) {
searchScope = GlobalSearchScopesCore.projectTestScope(myProject);
} else {
final NamedScope namedScope = NamedScopesHolder.getScope(myProject, scopeType);
if (namedScope != null) {
searchScope = GlobalSearchScopesCore.filterScope(myProject, namedScope);
}
}
return searchScope;
}
protected boolean isInScope(final PsiElement baseClass, final PsiElement srcElement, final String scopeType) {
if (HierarchyBrowserBaseEx.SCOPE_CLASS.equals(scopeType)) {
if (!PsiTreeUtil.isAncestor(baseClass, srcElement, true)) {
return false;
}
}
else if (HierarchyBrowserBaseEx.SCOPE_PROJECT.equals(scopeType)) {
final VirtualFile virtualFile = srcElement.getContainingFile().getVirtualFile();
if (virtualFile != null && ProjectRootManager.getInstance(myProject).getFileIndex().isInTestSourceContent(virtualFile)) {
return false;
}
}
else if (HierarchyBrowserBaseEx.SCOPE_TEST.equals(scopeType)) {
final VirtualFile virtualFile = srcElement.getContainingFile().getVirtualFile();
if (virtualFile != null && !ProjectRootManager.getInstance(myProject).getFileIndex().isInTestSourceContent(virtualFile)) {
return false;
}
} else if (!HierarchyBrowserBaseEx.SCOPE_ALL.equals(scopeType)) {
final NamedScope namedScope = NamedScopesHolder.getScope(myProject, scopeType);
if (namedScope == null) {
return false;
}
final PackageSet namedScopePattern = namedScope.getValue();
if (namedScopePattern == null) {
return false;
}
final PsiFile psiFile = srcElement.getContainingFile();
if (psiFile != null && !namedScopePattern.contains(psiFile, NamedScopesHolder.getHolder(myProject, scopeType, NamedScopeManager.getInstance(myProject)))) {
return false;
}
}
return true;
}
private static final class TextInfoNodeDescriptor extends NodeDescriptor {
public TextInfoNodeDescriptor(final NodeDescriptor parentDescriptor, final String text, final Project project) {
super(project, parentDescriptor);
myName = text;
myColor = JBColor.RED;
}
@Override
public final Object getElement() {
return myName;
}
@Override
public final boolean update() {
return true;
}
}
public boolean isAlwaysShowPlus() {
return false;
}
}