• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
getJavaClassDescriptornull54 fun 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
PsiFieldnull60 fun 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
getJavaMemberDescriptornull66 fun 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
getJavaOrKotlinMemberDescriptornull77 fun 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 
getJavaDescriptorResolvernull89 private fun PsiElement.getJavaDescriptorResolver(resolutionFacade: ResolutionFacade): JavaDescriptorResolver? {
90     return resolutionFacade.tryGetFrontendService(this, JavaDescriptorResolver::class.java)
91 }
92 
resolveMethodnull93 private 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 
resolveConstructornull100 private fun JavaDescriptorResolver.resolveConstructor(constructor: JavaConstructor): ConstructorDescriptor? {
101     return resolveClass(constructor.containingClass)?.constructors?.findByJavaElement(constructor)
102 }
103 
resolveFieldnull104 private fun JavaDescriptorResolver.resolveField(field: JavaField): PropertyDescriptor? {
105     return getContainingScope(field)?.getContributedVariables(field.name, NoLookupLocation.FROM_IDE)?.findByJavaElement(field)
106 }
107 
getContainingScopenull108 private 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 
findByJavaElementnull116 private 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 
javaResolutionFacadenull130 fun PsiElement.javaResolutionFacade() =
131     KotlinCacheService.getInstance(project).getResolutionFacadeByFile(this.originalElement.containingFile, JvmPlatform)!!
132