1 /* <lambda>null2 * Copyright 2010-2017 JetBrains s.r.o. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 @file:JvmName("JavaResolutionUtils") 18 19 package org.jetbrains.dokka 20 21 import com.intellij.psi.* 22 import org.jetbrains.kotlin.asJava.classes.KtLightClass 23 import org.jetbrains.kotlin.asJava.unwrapped 24 import org.jetbrains.kotlin.caches.resolve.KotlinCacheService 25 import org.jetbrains.kotlin.descriptors.* 26 import org.jetbrains.kotlin.idea.resolve.ResolutionFacade 27 import org.jetbrains.kotlin.incremental.components.NoLookupLocation 28 import org.jetbrains.kotlin.load.java.sources.JavaSourceElement 29 import org.jetbrains.kotlin.load.java.structure.* 30 import org.jetbrains.kotlin.load.java.structure.impl.* 31 import org.jetbrains.kotlin.name.Name 32 import org.jetbrains.kotlin.psi.KtClassOrObject 33 import org.jetbrains.kotlin.psi.KtDeclaration 34 import org.jetbrains.kotlin.psi.psiUtil.parameterIndex 35 import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver 36 import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform 37 import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter 38 import org.jetbrains.kotlin.resolve.scopes.MemberScope 39 40 // TODO: Remove that file 41 42 @JvmOverloads 43 fun PsiMethod.getJavaMethodDescriptor(resolutionFacade: ResolutionFacade = javaResolutionFacade()): DeclarationDescriptor? { 44 val method = originalElement as? PsiMethod ?: return null 45 if (method.containingClass == null || !Name.isValidIdentifier(method.name)) return null 46 val resolver = method.getJavaDescriptorResolver(resolutionFacade) 47 return when { 48 method.isConstructor -> resolver?.resolveConstructor(JavaConstructorImpl(method)) 49 else -> resolver?.resolveMethod(JavaMethodImpl(method)) 50 } 51 } 52 53 @JvmOverloads getJavaClassDescriptornull54fun PsiClass.getJavaClassDescriptor(resolutionFacade: ResolutionFacade = javaResolutionFacade()): ClassDescriptor? { 55 val psiClass = originalElement as? PsiClass ?: return null 56 return psiClass.getJavaDescriptorResolver(resolutionFacade)?.resolveClass(JavaClassImpl(psiClass)) 57 } 58 59 @JvmOverloads PsiFieldnull60fun PsiField.getJavaFieldDescriptor(resolutionFacade: ResolutionFacade = javaResolutionFacade()): PropertyDescriptor? { 61 val field = originalElement as? PsiField ?: return null 62 return field.getJavaDescriptorResolver(resolutionFacade)?.resolveField(JavaFieldImpl(field)) 63 } 64 65 @JvmOverloads getJavaMemberDescriptornull66fun PsiMember.getJavaMemberDescriptor(resolutionFacade: ResolutionFacade = javaResolutionFacade()): DeclarationDescriptor? { 67 return when (this) { 68 is PsiEnumConstant -> containingClass?.getJavaClassDescriptor(resolutionFacade) 69 is PsiClass -> getJavaClassDescriptor(resolutionFacade) 70 is PsiMethod -> getJavaMethodDescriptor(resolutionFacade) 71 is PsiField -> getJavaFieldDescriptor(resolutionFacade) 72 else -> null 73 } 74 } 75 76 @JvmOverloads getJavaOrKotlinMemberDescriptornull77fun PsiMember.getJavaOrKotlinMemberDescriptor(resolutionFacade: ResolutionFacade = javaResolutionFacade()): DeclarationDescriptor? { 78 val callable = unwrapped 79 return when (callable) { 80 is PsiMember -> getJavaMemberDescriptor(resolutionFacade) 81 is KtDeclaration -> { 82 val descriptor = resolutionFacade.resolveToDescriptor(callable) 83 if (descriptor is ClassDescriptor && this is PsiMethod) descriptor.unsubstitutedPrimaryConstructor else descriptor 84 } 85 else -> null 86 } 87 } 88 getJavaDescriptorResolvernull89private fun PsiElement.getJavaDescriptorResolver(resolutionFacade: ResolutionFacade): JavaDescriptorResolver? { 90 return resolutionFacade.tryGetFrontendService(this, JavaDescriptorResolver::class.java) 91 } 92 resolveMethodnull93private fun JavaDescriptorResolver.resolveMethod(method: JavaMethod): DeclarationDescriptor? { 94 return getContainingScope(method) 95 ?.getContributedDescriptors(nameFilter = { true }, kindFilter = DescriptorKindFilter.CALLABLES) 96 ?.filterIsInstance<DeclarationDescriptorWithSource>() 97 ?.findByJavaElement(method) 98 } 99 resolveConstructornull100private fun JavaDescriptorResolver.resolveConstructor(constructor: JavaConstructor): ConstructorDescriptor? { 101 return resolveClass(constructor.containingClass)?.constructors?.findByJavaElement(constructor) 102 } 103 resolveFieldnull104private fun JavaDescriptorResolver.resolveField(field: JavaField): PropertyDescriptor? { 105 return getContainingScope(field)?.getContributedVariables(field.name, NoLookupLocation.FROM_IDE)?.findByJavaElement(field) 106 } 107 getContainingScopenull108private fun JavaDescriptorResolver.getContainingScope(member: JavaMember): MemberScope? { 109 val containingClass = resolveClass(member.containingClass) 110 return if (member.isStatic) 111 containingClass?.staticScope 112 else 113 containingClass?.defaultType?.memberScope 114 } 115 findByJavaElementnull116private fun <T : DeclarationDescriptorWithSource> Collection<T>.findByJavaElement(javaElement: JavaElement): T? { 117 return firstOrNull { member -> 118 val memberJavaElement = (member.original.source as? JavaSourceElement)?.javaElement 119 when { 120 memberJavaElement == javaElement -> 121 true 122 memberJavaElement is JavaElementImpl<*> && javaElement is JavaElementImpl<*> -> 123 memberJavaElement.psi.isEquivalentTo(javaElement.psi) 124 else -> 125 false 126 } 127 } 128 } 129 javaResolutionFacadenull130fun PsiElement.javaResolutionFacade() = 131 KotlinCacheService.getInstance(project).getResolutionFacadeByFile(this.originalElement.containingFile, JvmPlatform)!! 132