Fix origin for TypeParameter + refactoring

This commit is contained in:
Igor Yakovlev
2019-04-23 19:57:40 +03:00
parent f20ba9ddc2
commit 8e103b6559
5 changed files with 78 additions and 24 deletions
@@ -0,0 +1,39 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.asJava.classes
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.intellij.psi.PsiTypeParameterListOwner
import com.intellij.psi.impl.light.LightReferenceListBuilder
import com.intellij.psi.impl.light.LightTypeParameterBuilder
import org.jetbrains.kotlin.asJava.elements.PsiElementWithOrigin
import org.jetbrains.kotlin.asJava.unwrapped
import org.jetbrains.kotlin.psi.KtTypeParameter
import org.jetbrains.kotlin.psi.KtTypeParameterListOwner
internal class KtUltraLightTypeParameter(
name: String,
private val myOwner: PsiTypeParameterListOwner,
private val myParent: PsiElement,
index: Int,
referenceListBuilder: (PsiElement) -> KotlinLightReferenceListBuilder
) :
LightTypeParameterBuilder(name, myOwner, index),
PsiElementWithOrigin<KtTypeParameter> {
private val superList: LightReferenceListBuilder by lazyPub { referenceListBuilder(this) }
override val origin: KtTypeParameter get() = (myOwner.unwrapped as KtTypeParameterListOwner).typeParameters[index]
override fun getExtendsList(): LightReferenceListBuilder = superList
override fun getParent(): PsiElement = myParent
override fun getContainingFile(): PsiFile = myOwner.containingFile
override fun getUseScope() = origin.useScope
}
@@ -12,10 +12,12 @@ import com.intellij.psi.impl.compiled.ClsTypeElementImpl
import com.intellij.psi.impl.compiled.SignatureParsing
import com.intellij.psi.impl.compiled.StubBuildingVisitor
import com.intellij.psi.impl.light.*
import com.intellij.psi.search.SearchScope
import com.intellij.util.BitUtil.isSet
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
import org.jetbrains.kotlin.asJava.elements.KotlinLightTypeParameterListBuilder
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.asJava.unwrapped
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.JvmCodegenUtil
@@ -25,10 +27,7 @@ import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtTypeParameter
import org.jetbrains.kotlin.psi.KtTypeParameterListOwner
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.types.KotlinType
@@ -90,33 +89,35 @@ internal fun <D, T> buildTypeParameterList(
support: UltraLightSupport,
typeParametersSupport: TypeParametersSupport<D, T>
): PsiTypeParameterList {
val tpList = KotlinLightTypeParameterListBuilder(owner)
for ((i, param) in typeParametersSupport.parameters(declaration).withIndex()) {
tpList.addParameter(object : LightTypeParameterBuilder(typeParametersSupport.name(param).orEmpty(), owner, i) {
private val superList: LightReferenceListBuilder by lazyPub {
val boundList =
KotlinLightReferenceListBuilder(manager, PsiReferenceList.Role.EXTENDS_BOUNDS_LIST)
if (typeParametersSupport.hasNonTrivialBounds(declaration, param)) {
val boundTypes = typeParametersSupport.asDescriptor(param)?.upperBounds.orEmpty()
.mapNotNull { it.asPsiType(support, TypeMappingMode.DEFAULT, this) as? PsiClassType }
val hasDefaultBound = boundTypes.size == 1 && boundTypes[0].equalsToText(CommonClassNames.JAVA_LANG_OBJECT)
if (!hasDefaultBound) {
boundTypes.forEach(boundList::addReference)
}
}
boundList
val referenceListBuilder = { element: PsiElement ->
val boundList = KotlinLightReferenceListBuilder(element.manager, PsiReferenceList.Role.EXTENDS_BOUNDS_LIST)
if (typeParametersSupport.hasNonTrivialBounds(declaration, param)) {
val boundTypes = typeParametersSupport.asDescriptor(param)
?.upperBounds
.orEmpty()
.mapNotNull { it.asPsiType(support, TypeMappingMode.DEFAULT, element) as? PsiClassType }
val hasDefaultBound = boundTypes.size == 1 && boundTypes[0].equalsToText(CommonClassNames.JAVA_LANG_OBJECT)
if (!hasDefaultBound) boundTypes.forEach(boundList::addReference)
}
boundList
}
override fun getExtendsList(): LightReferenceListBuilder = superList
val parameterName = typeParametersSupport.name(param).orEmpty()
override fun getParent(): PsiElement = tpList
override fun getContainingFile(): PsiFile = owner.containingFile
})
tpList.addParameter(KtUltraLightTypeParameter(parameterName, owner, tpList, i, referenceListBuilder))
}
return tpList
}
internal fun KtDeclaration.getKotlinType(): KotlinType? {
val descriptor = resolve()
return when (descriptor) {
@@ -29,8 +29,9 @@ import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
open class KtLightIdentifier(
private val lightOwner: PsiElement,
private val ktDeclaration: KtNamedDeclaration?
) : LightIdentifier(lightOwner.manager, ktDeclaration?.name ?: ""), PsiCompiledElement {
val origin: PsiElement?
) : LightIdentifier(lightOwner.manager, ktDeclaration?.name ?: ""), PsiCompiledElement,
PsiElementWithOrigin<PsiElement> {
override val origin: PsiElement?
get() = when (ktDeclaration) {
is KtSecondaryConstructor -> ktDeclaration.getConstructorKeyword()
is KtPrimaryConstructor -> ktDeclaration.getConstructorKeyword()
@@ -0,0 +1,12 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.asJava.elements
import com.intellij.psi.PsiElement
interface PsiElementWithOrigin<out T> : PsiElement where T : PsiElement {
val origin: T?
}
@@ -20,6 +20,7 @@ import com.intellij.psi.*
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
import org.jetbrains.kotlin.asJava.elements.PsiElementWithOrigin
import org.jetbrains.kotlin.asJava.elements.*
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
import org.jetbrains.kotlin.load.java.JvmAbi
@@ -137,8 +138,8 @@ fun KtTypeParameter.toPsiTypeParameters(): List<PsiTypeParameter> {
// Returns original declaration if given PsiElement is a Kotlin light element, and element itself otherwise
val PsiElement.unwrapped: PsiElement?
get() = when {
this is PsiElementWithOrigin<*> -> origin
this is KtLightElement<*, *> -> kotlinOrigin
this is KtLightIdentifier -> origin
this is KtLightElementBase -> kotlinOrigin
else -> this
}