/* * 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.source; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import consulo.annotations.RequiredReadAction; import consulo.csharp.lang.psi.CSharpMethodDeclaration; import consulo.csharp.lang.psi.impl.msil.CSharpTransform; import consulo.csharp.lang.psi.impl.partial.CSharpCompositeTypeDeclaration; import consulo.csharp.lang.psi.impl.source.resolve.type.CSharpTypeRefByQName; import consulo.dotnet.DotNetTypes; import consulo.dotnet.psi.DotNetNamedElement; import consulo.dotnet.psi.DotNetTypeDeclaration; import consulo.dotnet.psi.DotNetTypeList; import consulo.dotnet.resolve.DotNetGenericExtractor; import consulo.dotnet.resolve.DotNetPsiSearcher; import consulo.dotnet.resolve.DotNetTypeRef; import consulo.dotnet.resolve.DotNetTypeResolveResult; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Pair; import com.intellij.psi.PsiElement; import com.intellij.util.ArrayUtil; /** * @author VISTALL * @since 17.05.14 */ public class CSharpTypeDeclarationImplUtil { @RequiredReadAction public static boolean isInheritOrSelf(@NotNull DotNetTypeRef typeRef, @NotNull PsiElement scope, @NotNull String... vmQNames) { DotNetTypeResolveResult typeResolveResult = typeRef.resolve(); PsiElement typeResolveResultElement = typeResolveResult.getElement(); if(!(typeResolveResultElement instanceof DotNetTypeDeclaration)) { return false; } return isInheritOrSelf0((DotNetTypeDeclaration) typeResolveResultElement, vmQNames); } @RequiredReadAction private static boolean isInheritOrSelf0(DotNetTypeDeclaration typeDeclaration, String... vmQNames) { if(ArrayUtil.contains(typeDeclaration.getVmQName(), vmQNames)) { return true; } DotNetTypeRef[] anExtends = typeDeclaration.getExtendTypeRefs(); if(anExtends.length > 0) { for(DotNetTypeRef dotNetType : anExtends) { PsiElement psiElement = dotNetType.resolve().getElement(); if(psiElement instanceof DotNetTypeDeclaration) { if(psiElement.isEquivalentTo(typeDeclaration)) { return false; } if(ArrayUtil.contains(((DotNetTypeDeclaration) psiElement).getVmQName(), vmQNames)) { return true; } if(isInheritOrSelf0((DotNetTypeDeclaration) psiElement, vmQNames)) { return true; } } } } return false; } @RequiredReadAction public static boolean isEquivalentTo(@NotNull DotNetTypeDeclaration thisType, @Nullable PsiElement another) { return another instanceof DotNetTypeDeclaration && Comparing.equal(thisType.getVmQName(), ((DotNetTypeDeclaration) another).getVmQName()); } public static boolean hasExtensions(@NotNull DotNetTypeDeclaration typeDeclaration) { for(DotNetNamedElement qualifiedElement : typeDeclaration.getMembers()) { if(qualifiedElement instanceof CSharpMethodDeclaration && ((CSharpMethodDeclaration) qualifiedElement).isExtension()) { return true; } } return false; } @RequiredReadAction @NotNull public static DotNetTypeRef[] getExtendTypeRefs(@NotNull DotNetTypeDeclaration typeDeclaration) { DotNetTypeRef[] typeRefs = DotNetTypeRef.EMPTY_ARRAY; DotNetTypeList extendList = typeDeclaration.getExtendList(); if(extendList != null && !typeDeclaration.isEnum()) { typeRefs = extendList.getTypeRefs(); } if(typeRefs.length == 0) { String defaultSuperType = getDefaultSuperType(typeDeclaration); if(defaultSuperType == null) { return DotNetTypeRef.EMPTY_ARRAY; } typeRefs = new DotNetTypeRef[]{new CSharpTypeRefByQName(typeDeclaration, defaultSuperType)}; } return typeRefs; } @Nullable @RequiredReadAction public static Pair<DotNetTypeDeclaration, DotNetGenericExtractor> resolveBaseType(@NotNull DotNetTypeDeclaration typeDeclaration, @NotNull PsiElement scope) { typeDeclaration = CSharpCompositeTypeDeclaration.selectCompositeOrSelfType(typeDeclaration); DotNetTypeRef[] anExtends = typeDeclaration.getExtendTypeRefs(); if(anExtends.length != 0) { for(DotNetTypeRef anExtend : anExtends) { DotNetTypeResolveResult resolveResult = anExtend.resolve(); PsiElement resolve = resolveResult.getElement(); if(resolve instanceof DotNetTypeDeclaration && !((DotNetTypeDeclaration) resolve).isInterface()) { return Pair.create((DotNetTypeDeclaration) resolve, resolveResult.getGenericExtractor()); } } } String defaultSuperType = getDefaultSuperType(typeDeclaration); if(defaultSuperType != null) { DotNetTypeDeclaration type = DotNetPsiSearcher.getInstance(typeDeclaration.getProject()).findType(defaultSuperType, scope.getResolveScope(), CSharpTransform.INSTANCE); if(type != null) { return Pair.create(type, DotNetGenericExtractor.EMPTY); } } return null; } @Nullable @RequiredReadAction public static String getDefaultSuperType(@NotNull DotNetTypeDeclaration typeDeclaration) { String vmQName = typeDeclaration.getVmQName(); if(Comparing.equal(vmQName, DotNetTypes.System.Object)) { return null; } if(typeDeclaration.isStruct()) { return DotNetTypes.System.ValueType; } else if(typeDeclaration.isEnum()) { return DotNetTypes.System.Enum; } else { return DotNetTypes.System.Object; } } }