/* * Copyright 2013-2017 consulo.io * * 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 consulo.csharp.ide.projectView; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import javax.annotation.Nullable; import com.intellij.ide.projectView.PresentationData; import com.intellij.ide.projectView.ViewSettings; import com.intellij.ide.util.treeView.AbstractTreeNode; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.io.FileUtil; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiNamedElement; import com.intellij.util.BitUtil; import com.intellij.util.containers.ContainerUtil; import consulo.ui.annotation.RequiredUIAccess; import consulo.annotation.access.RequiredReadAction; import consulo.csharp.ide.CSharpElementPresentationUtil; import consulo.csharp.lang.psi.CSharpElementVisitor; import consulo.csharp.lang.psi.CSharpMethodDeclaration; import consulo.csharp.lang.psi.CSharpTypeDeclaration; import consulo.dotnet.ide.DotNetElementPresentationUtil; import consulo.dotnet.psi.*; import consulo.dotnet.resolve.DotNetTypeRef; /** * @author VISTALL * @since 09.12.13. */ public class CSharpElementTreeNode extends CSharpAbstractElementTreeNode<DotNetNamedElement> { public static int getWeight(PsiElement element) { int defaultWeight = getDefaultWeight(element); if(element instanceof DotNetVirtualImplementOwner) { DotNetTypeRef typeRefForImplement = ((DotNetVirtualImplementOwner) element).getTypeRefForImplement(); if(typeRefForImplement != DotNetTypeRef.ERROR_TYPE) { return -defaultWeight; } } return 0; } private static int getDefaultWeight(PsiElement element) { if(element instanceof DotNetNamespaceDeclaration) { return 100; } else if(element instanceof DotNetTypeDeclaration) { return 200; } else if(element instanceof DotNetFieldDeclaration) { return 300; } else if(element instanceof DotNetPropertyDeclaration) { return 400; } else if(element instanceof DotNetEventDeclaration) { return 500; } else if(element instanceof DotNetConstructorDeclaration) { return 700; } else if(element instanceof DotNetLikeMethodDeclaration) { return 600; } return 0; } // force expand members for root file nodes (if not than one) public static final int FORCE_EXPAND = 1 << 0; // if we have solo type - but file name is not equal public static final int ALLOW_GRAY_FILE_NAME = 1 << 1; private final int myFlags; public CSharpElementTreeNode(DotNetNamedElement dotNetMemberOwner, ViewSettings viewSettings, int flags) { super(dotNetMemberOwner.getProject(), dotNetMemberOwner, viewSettings); myFlags = flags; } @Override public int getWeight() { // namespace // type // field // property // event // constructor // method DotNetNamedElement element = getValue(); int weight = getWeight(element); if(weight != 0) { return weight; } return super.getWeight(); } @Nullable @Override @RequiredUIAccess protected Collection<AbstractTreeNode> getChildrenImpl() { final ViewSettings settings = getSettings(); if(!settings.isShowMembers() && !BitUtil.isSet(myFlags, FORCE_EXPAND)) { return Collections.emptyList(); } DotNetNamedElement[] members = filterNamespaces(getValue()); if(members.length == 0) { return Collections.emptyList(); } List<AbstractTreeNode> list = new ArrayList<>(members.length); for(DotNetNamedElement dotNetElement : members) { list.add(new CSharpElementTreeNode(dotNetElement, settings, 0)); } return list; } @RequiredReadAction private static DotNetNamedElement[] filterNamespaces(DotNetElement declaration) { if(declaration instanceof DotNetMemberOwner) { List<DotNetNamedElement> elements = new ArrayList<>(); DotNetNamedElement[] members = ((DotNetMemberOwner) declaration).getMembers(); for(DotNetNamedElement member : members) { if(member instanceof DotNetNamespaceDeclaration) { member.accept(new CSharpElementVisitor() { @Override @RequiredReadAction public void visitElement(PsiElement element) { ProgressManager.checkCanceled(); if(element instanceof DotNetMemberOwner) { for(DotNetNamedElement namedElement : ((DotNetMemberOwner) element).getMembers()) { namedElement.accept(this); } } } @Override public void visitTypeDeclaration(CSharpTypeDeclaration declaration) { if(!declaration.isNested()) { elements.add(declaration); } } @Override public void visitMethodDeclaration(CSharpMethodDeclaration declaration) { if(declaration.isDelegate()) { elements.add(declaration); } } }); } else { elements.add(member); } } return ContainerUtil.toArray(elements, DotNetNamedElement.ARRAY_FACTORY); } return DotNetNamedElement.EMPTY_ARRAY; } @Override public boolean isAlwaysExpand() { return super.isAlwaysExpand() || BitUtil.isSet(myFlags, FORCE_EXPAND); } @Override @RequiredUIAccess protected void updateImpl(PresentationData presentationData) { DotNetNamedElement value = getValue(); presentationData.setPresentableText(getPresentableText(value)); if(BitUtil.isSet(myFlags, ALLOW_GRAY_FILE_NAME)) { PsiFile containingFile = value.getContainingFile(); if(containingFile != null) { if(!Comparing.equal(FileUtil.getNameWithoutExtension(containingFile.getName()), value.getName())) { presentationData.setLocationString(containingFile.getName()); } } } } @RequiredReadAction public static String getPresentableText(PsiNamedElement value) { if(value instanceof DotNetLikeMethodDeclaration) { return CSharpElementPresentationUtil.formatMethod((DotNetLikeMethodDeclaration) value, CSharpElementPresentationUtil.METHOD_SCALA_LIKE_FULL); } else if(value instanceof DotNetFieldDeclaration) { return CSharpElementPresentationUtil.formatField((DotNetFieldDeclaration) value); } else if(value instanceof DotNetNamespaceDeclaration) { return ((DotNetNamespaceDeclaration) value).getPresentableQName(); } else if(value instanceof DotNetTypeDeclaration) { return DotNetElementPresentationUtil.formatTypeWithGenericParameters((DotNetTypeDeclaration) value); } else { return value.getName(); } } }