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.unwrapped 23 import org.jetbrains.kotlin.caches.resolve.KotlinCacheService 24 import org.jetbrains.kotlin.descriptors.* 25 import org.jetbrains.kotlin.idea.resolve.ResolutionFacade 26 import org.jetbrains.kotlin.incremental.components.NoLookupLocation 27 import org.jetbrains.kotlin.load.java.sources.JavaSourceElement 28 import org.jetbrains.kotlin.load.java.structure.* 29 import org.jetbrains.kotlin.load.java.structure.impl.* 30 import org.jetbrains.kotlin.name.Name 31 import org.jetbrains.kotlin.platform.jvm.JvmPlatforms 32 import org.jetbrains.kotlin.psi.KtDeclaration 33 import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver 34 import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter 35 import org.jetbrains.kotlin.resolve.scopes.MemberScope 36 37 // TODO: Remove that file 38 39 @JvmOverloads 40 fun PsiMethod.getJavaMethodDescriptor(resolutionFacade: ResolutionFacade = javaResolutionFacade()): DeclarationDescriptor? { 41 val method = originalElement as? PsiMethod ?: return null 42 if (method.containingClass == null || !Name.isValidIdentifier(method.name)) return null 43 val resolver = method.getJavaDescriptorResolver(resolutionFacade) 44 return when { 45 method.isConstructor -> resolver?.resolveConstructor(JavaConstructorImpl(method)) 46 else -> resolver?.resolveMethod(JavaMethodImpl(method)) 47 } 48 } 49 50 @JvmOverloads getJavaClassDescriptornull51fun PsiClass.getJavaClassDescriptor(resolutionFacade: ResolutionFacade = javaResolutionFacade()): ClassDescriptor? { 52 val psiClass = originalElement as? PsiClass ?: return null 53 return psiClass.getJavaDescriptorResolver(resolutionFacade)?.resolveClass(JavaClassImpl(psiClass)) 54 } 55 56 @JvmOverloads PsiFieldnull57fun PsiField.getJavaFieldDescriptor(resolutionFacade: ResolutionFacade = javaResolutionFacade()): PropertyDescriptor? { 58 val field = originalElement as? PsiField ?: return null 59 return field.getJavaDescriptorResolver(resolutionFacade)?.resolveField(JavaFieldImpl(field)) 60 } 61 62 @JvmOverloads getJavaMemberDescriptornull63fun PsiMember.getJavaMemberDescriptor(resolutionFacade: ResolutionFacade = javaResolutionFacade()): DeclarationDescriptor? { 64 return when (this) { 65 is PsiEnumConstant -> containingClass?.getJavaClassDescriptor(resolutionFacade) 66 is PsiClass -> getJavaClassDescriptor(resolutionFacade) 67 is PsiMethod -> getJavaMethodDescriptor(resolutionFacade) 68 is PsiField -> getJavaFieldDescriptor(resolutionFacade) 69 else -> null 70 } 71 } 72 73 @JvmOverloads getJavaOrKotlinMemberDescriptornull74fun PsiMember.getJavaOrKotlinMemberDescriptor(resolutionFacade: ResolutionFacade = javaResolutionFacade()): DeclarationDescriptor? { 75 val callable = unwrapped 76 return when (callable) { 77 is PsiMember -> getJavaMemberDescriptor(resolutionFacade) 78 is KtDeclaration -> { 79 val descriptor = resolutionFacade.resolveToDescriptor(callable) 80 if (descriptor is ClassDescriptor && this is PsiMethod) descriptor.unsubstitutedPrimaryConstructor else descriptor 81 } 82 else -> null 83 } 84 } 85 getJavaDescriptorResolvernull86private fun PsiElement.getJavaDescriptorResolver(resolutionFacade: ResolutionFacade): JavaDescriptorResolver? { 87 return resolutionFacade.tryGetFrontendService(this, JavaDescriptorResolver::class.java) 88 } 89 resolveMethodnull90private fun JavaDescriptorResolver.resolveMethod(method: JavaMethod): DeclarationDescriptor? { 91 return getContainingScope(method) 92 ?.getContributedDescriptors(nameFilter = { true }, kindFilter = DescriptorKindFilter.CALLABLES) 93 ?.filterIsInstance<DeclarationDescriptorWithSource>() 94 ?.findByJavaElement(method) 95 } 96 resolveConstructornull97private fun JavaDescriptorResolver.resolveConstructor(constructor: JavaConstructor): ConstructorDescriptor? { 98 return resolveClass(constructor.containingClass)?.constructors?.findByJavaElement(constructor) 99 } 100 resolveFieldnull101private fun JavaDescriptorResolver.resolveField(field: JavaField): PropertyDescriptor? { 102 return getContainingScope(field)?.getContributedVariables(field.name, NoLookupLocation.FROM_IDE)?.findByJavaElement(field) 103 } 104 getContainingScopenull105private fun JavaDescriptorResolver.getContainingScope(member: JavaMember): MemberScope? { 106 val containingClass = resolveClass(member.containingClass) 107 return if (member.isStatic) 108 containingClass?.staticScope 109 else 110 containingClass?.defaultType?.memberScope 111 } 112 findByJavaElementnull113private fun <T : DeclarationDescriptorWithSource> Collection<T>.findByJavaElement(javaElement: JavaElement): T? { 114 return firstOrNull { member -> 115 val memberJavaElement = (member.original.source as? JavaSourceElement)?.javaElement 116 when { 117 memberJavaElement == javaElement -> 118 true 119 memberJavaElement is JavaElementImpl<*> && javaElement is JavaElementImpl<*> -> 120 memberJavaElement.psi.isEquivalentTo(javaElement.psi) 121 else -> 122 false 123 } 124 } 125 } 126 javaResolutionFacadenull127fun PsiElement.javaResolutionFacade() = 128 KotlinCacheService.getInstance(project).getResolutionFacadeByFile(this.originalElement.containingFile, JvmPlatforms.defaultJvmPlatform)!! 129