/* * 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.lang.psi.impl; import java.util.List; import javax.annotation.Nonnull; import com.intellij.psi.PsiElement; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.SmartList; import consulo.annotation.access.RequiredReadAction; import consulo.csharp.lang.psi.CSharpAccessModifier; import consulo.csharp.lang.psi.CSharpTypeDeclaration; import consulo.csharp.lang.psi.impl.partial.CSharpCompositeTypeDeclaration; import consulo.csharp.lang.psi.impl.runtime.AssemblyModule; import consulo.dotnet.psi.DotNetInheritUtil; import consulo.dotnet.psi.DotNetModifierListOwner; import consulo.dotnet.psi.DotNetTypeDeclaration; /** * @author VISTALL * @since 08.03.14 */ public class CSharpVisibilityUtil { @RequiredReadAction public static boolean isVisible(@Nonnull DotNetModifierListOwner target, @Nonnull PsiElement place) { return isVisible(target, place, CSharpAccessModifier.findModifierOrDefault(target)); } @RequiredReadAction private static boolean isVisible(DotNetModifierListOwner target, PsiElement place, CSharpAccessModifier accessModifier) { switch(accessModifier) { case PUBLIC: case NONE: return true; case PROTECTED_INTERNAL: return isVisible(target, place, CSharpAccessModifier.INTERNAL); case INTERNAL: AssemblyModule targetModule = AssemblyModule.resolve(target); AssemblyModule placeModule = AssemblyModule.resolve(place); if(targetModule.equals(placeModule)) { return true; } String placeAssemblyName = placeModule.getName(); return targetModule.isAllowedAssembly(placeAssemblyName); case PROTECTED: { List<DotNetTypeDeclaration> targetTypes = collectAllTypes(target); List<DotNetTypeDeclaration> placeTypes = collectAllTypes(place); for(DotNetTypeDeclaration placeType : placeTypes) { final DotNetTypeDeclaration type = CSharpCompositeTypeDeclaration.selectCompositeOrSelfType(placeType); for(DotNetTypeDeclaration targetType : targetTypes) { String vmQName = targetType.getVmQName(); assert vmQName != null; if(DotNetInheritUtil.isParentOrSelf(vmQName, type, true)) { return true; } } } break; } case PRIVATE: { List<DotNetTypeDeclaration> targetTypes = collectAllTypes(target); List<DotNetTypeDeclaration> placeTypes = collectAllTypes(place); for(DotNetTypeDeclaration placeType : placeTypes) { for(DotNetTypeDeclaration type : targetTypes) { if(placeType.isEquivalentTo(type)) { return true; } } } break; } } return false; } @Nonnull @RequiredReadAction private static List<DotNetTypeDeclaration> collectAllTypes(@Nonnull PsiElement place) { List<DotNetTypeDeclaration> typeDeclarations = new SmartList<>(); if(place instanceof CSharpTypeDeclaration) { typeDeclarations.add((DotNetTypeDeclaration) place); } PsiElement type = place; while((type = PsiTreeUtil.getContextOfType(type, DotNetTypeDeclaration.class)) != null) { typeDeclarations.add((DotNetTypeDeclaration) type); } return typeDeclarations; } }