Return Kotlin fields and methods through KotlinShortNameCache

#KT-12205 Fixed
This commit is contained in:
Simon Ogorodnik
2016-08-30 19:49:10 +03:00
committed by Dmitry Jemerov
parent b06bdcef75
commit 18feb8f622
28 changed files with 1156 additions and 57 deletions
@@ -16,14 +16,12 @@
package org.jetbrains.kotlin.asJava
import com.intellij.openapi.progress.ProcessCanceledException
import com.intellij.psi.*
import com.intellij.psi.impl.java.stubs.PsiClassStub
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.stubs.PsiFileStub
import com.intellij.psi.stubs.StubElement
import com.intellij.psi.util.PsiTreeUtil
import com.intellij.util.SmartList
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.elements.*
import org.jetbrains.kotlin.asJava.finder.JavaElementFinder
@@ -31,6 +29,7 @@ import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
import org.jetbrains.kotlin.utils.addToStdlib.sequenceOfLazyValues
object LightClassUtil {
@@ -53,9 +52,11 @@ object LightClassUtil {
fun getLightClassAccessorMethods(accessor: KtPropertyAccessor): List<PsiMethod> {
val property = accessor.getNonStrictParentOfType<KtProperty>() ?: return emptyList()
val wrappers = getPsiMethodWrappers(property, true)
return wrappers.filter { wrapper -> (accessor.isGetter && !JvmAbi.isSetterName(wrapper.name)) ||
(accessor.isSetter && JvmAbi.isSetterName(wrapper.name)) }
val wrappers = getPsiMethodWrappers(property)
return wrappers.filter { wrapper ->
(accessor.isGetter && !JvmAbi.isSetterName(wrapper.name)) ||
(accessor.isSetter && JvmAbi.isSetterName(wrapper.name))
}.toList()
}
fun getLightFieldForCompanionObject(companionObject: KtClassOrObject): PsiField? {
@@ -120,36 +121,16 @@ object LightClassUtil {
}
fun getLightClassMethods(function: KtFunction): List<PsiMethod> {
return getPsiMethodWrappers(function, true)
return getPsiMethodWrappers(function).toList()
}
private fun getPsiMethodWrapper(declaration: KtDeclaration): PsiMethod? {
return getPsiMethodWrappers(declaration, false).firstOrNull()
return getPsiMethodWrappers(declaration).firstOrNull()
}
private fun getPsiMethodWrappers(declaration: KtDeclaration, collectAll: Boolean): List<PsiMethod> {
val psiClass = getWrappingClass(declaration) ?: return emptyList()
val methods = SmartList<PsiMethod>()
for (method in psiClass.methods.asList()) {
try {
if (method is KtLightMethod && method.kotlinOrigin === declaration) {
methods.add(method)
if (!collectAll) {
return methods
}
}
}
catch (e: ProcessCanceledException) {
throw e
}
catch (e: Throwable) {
throw IllegalStateException(
"Error while wrapping declaration " + declaration.name + "Context\n:" + method, e)
}
}
return methods
private fun getPsiMethodWrappers(declaration: KtDeclaration): Sequence<PsiMethod> {
return getWrappingClasses(declaration).flatMap { it.methods.asSequence() }
.filter { method -> method is KtLightMethod && method.kotlinOrigin === declaration }
}
private fun getWrappingClass(declaration: KtDeclaration): PsiClass? {
@@ -185,6 +166,15 @@ object LightClassUtil {
return null
}
private fun getWrappingClasses(declaration: KtDeclaration): Sequence<PsiClass> {
val wrapperClass = getWrappingClass(declaration) ?: return emptySequence()
val wrapperClassOrigin = (wrapperClass as KtLightClass).kotlinOrigin
if (wrapperClassOrigin is KtObjectDeclaration && wrapperClassOrigin.isCompanion()) {
return sequenceOfLazyValues({ wrapperClass }, { wrapperClass.parent as PsiClass })
}
return sequenceOf(wrapperClass)
}
fun canGenerateLightClass(declaration: KtDeclaration): Boolean {
//noinspection unchecked
return PsiTreeUtil.getParentOfType(declaration, KtFunction::class.java, KtProperty::class.java) == null
@@ -197,7 +187,7 @@ object LightClassUtil {
var setterWrapper = specialSetter
val additionalAccessors = arrayListOf<PsiMethod>()
for (wrapper in getPsiMethodWrappers(ktDeclaration, true)) {
for (wrapper in getPsiMethodWrappers(ktDeclaration)) {
if (wrapper !is KtLightMethod) continue
if (wrapper.isSetter) {
@@ -209,7 +199,7 @@ object LightClassUtil {
}
}
else {
if (getterWrapper == null || getterWrapper == specialGetter) {
if (getterWrapper == null || getterWrapper === specialGetter) {
getterWrapper = wrapper
}
else {
@@ -20,6 +20,7 @@ import com.intellij.psi.PsiElement
import com.intellij.psi.PsiField
import com.intellij.psi.PsiNamedElement
import com.intellij.psi.impl.PsiVariableEx
import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtElement
@@ -31,4 +32,6 @@ interface KtLightElement<out T : KtElement, out D : PsiElement> : PsiNamedElemen
interface KtLightDeclaration<out T: KtDeclaration, out D: PsiElement>: KtLightElement<T, D>
interface KtLightField : PsiField, KtLightDeclaration<KtDeclaration, PsiField>, PsiVariableEx
interface KtLightField : PsiField, KtLightDeclaration<KtDeclaration, PsiField>, PsiVariableEx {
val lightMemberOrigin: LightMemberOrigin?
}
@@ -16,6 +16,9 @@
package org.jetbrains.kotlin.asJava.elements
import com.intellij.navigation.ItemPresentation
import com.intellij.navigation.ItemPresentationProviders
import com.intellij.navigation.NavigationItem
import com.intellij.openapi.util.TextRange
import com.intellij.psi.*
import com.intellij.psi.impl.PsiVariableEx
@@ -30,10 +33,11 @@ import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtEnumEntry
import org.jetbrains.kotlin.psi.KtNamedDeclaration
import java.lang.UnsupportedOperationException
// Copied from com.intellij.psi.impl.light.LightField
sealed class KtLightFieldImpl(
private val lightMemberOrigin: LightMemberOrigin?,
override val lightMemberOrigin: LightMemberOrigin?,
override val clsDelegate: PsiField,
private val containingClass: KtLightClass
) : LightElement(clsDelegate.manager, KotlinLanguage.INSTANCE), KtLightField {
@@ -44,6 +48,8 @@ sealed class KtLightFieldImpl(
override fun getUseScope() = kotlinOrigin?.useScope ?: super.getUseScope()
override fun getPresentation(): ItemPresentation? = (kotlinOrigin ?: this).let { ItemPresentationProviders.getItemPresentation(it) }
override fun getName() = clsDelegate.name
override fun getNameIdentifier() = lightIdentifier
@@ -92,6 +98,20 @@ sealed class KtLightFieldImpl(
override fun toString(): String = "${this.javaClass.simpleName}:$name"
override fun equals(other: Any?): Boolean =
other is KtLightField &&
name == other.name &&
lightMemberOrigin == other.lightMemberOrigin &&
containingClass == other.containingClass &&
clsDelegate == other.clsDelegate
override fun hashCode(): Int {
var result = lightMemberOrigin?.hashCode() ?: 0
result = 31 * result + clsDelegate.hashCode()
result = 31 * result + containingClass.hashCode()
return result
}
override val kotlinOrigin: KtDeclaration? get() = lightMemberOrigin?.originalElement
override fun getNavigationElement() = kotlinOrigin ?: super.getNavigationElement()
@@ -111,6 +131,7 @@ sealed class KtLightFieldImpl(
override fun copy() = Factory.create(lightMemberOrigin?.copy(), clsDelegate, containingClass)
class KtLightEnumConstant(
origin: LightMemberOrigin?,
override val clsDelegate: PsiEnumConstant,
@@ -182,4 +182,8 @@ fun accessorNameByPropertyName(name: String, accessor: KtLightMethod): String? {
JvmAbi.isSetterName(methodName) -> JvmAbi.setterName(name)
else -> null
}
}
fun getAccessorNamesCandidatesByPropertyName(name: String): List<String> {
return listOf(JvmAbi.setterName(name), JvmAbi.getterName(name))
}