[ULC] Add annotations for PsiTypes in UltraLight classes
WIP on KT-41148, KT-41406, KT-41420
This commit is contained in:
@@ -145,7 +145,7 @@ internal open class KtUltraLightFieldImpl protected constructor(
|
||||
val kotlinType = declaration.getKotlinType() ?: return@lazyPub PsiType.NULL
|
||||
val descriptor = variableDescriptor ?: return@lazyPub PsiType.NULL
|
||||
|
||||
support.mapType(this) { typeMapper, sw ->
|
||||
support.mapType(kotlinType, this) { typeMapper, sw ->
|
||||
typeMapper.writeFieldSignature(kotlinType, descriptor, sw)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -243,7 +243,7 @@ internal class UltraLightMembersCreator(
|
||||
ktDeclaration.resolve()?.getterIfProperty() as? CallableDescriptor
|
||||
?: return PsiType.NULL
|
||||
|
||||
return support.mapType(wrapper) { typeMapper, signatureWriter ->
|
||||
return support.mapType(desc.returnType, wrapper) { typeMapper, signatureWriter ->
|
||||
typeMapper.mapReturnType(desc, signatureWriter)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,7 +258,7 @@ internal class KtUltraLightMethodForDescriptor(
|
||||
delegate.isConstructor = true
|
||||
PsiType.VOID
|
||||
} else {
|
||||
support.mapType(this) { typeMapper, signatureWriter ->
|
||||
support.mapType(methodDescriptor.returnType, this) { typeMapper, signatureWriter ->
|
||||
typeMapper.mapReturnType(methodDescriptor, signatureWriter)
|
||||
}
|
||||
}
|
||||
|
||||
+4
-2
@@ -9,6 +9,8 @@ import com.intellij.navigation.ItemPresentation
|
||||
import com.intellij.navigation.ItemPresentationProviders
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.impl.compiled.ClsTypeElementImpl
|
||||
import com.intellij.psi.impl.source.PsiClassReferenceType
|
||||
import com.intellij.psi.search.LocalSearchScope
|
||||
import com.intellij.psi.search.SearchScope
|
||||
import com.intellij.psi.util.TypeConversionUtil
|
||||
@@ -108,7 +110,6 @@ internal abstract class KtUltraLightParameter(
|
||||
override val psiTypeForNullabilityAnnotation: PsiType?
|
||||
get() = type
|
||||
|
||||
|
||||
protected fun computeParameterType(kotlinType: KotlinType?, containingDeclaration: CallableDescriptor?): PsiType {
|
||||
kotlinType ?: return PsiType.NULL
|
||||
|
||||
@@ -116,9 +117,10 @@ internal abstract class KtUltraLightParameter(
|
||||
return kotlinType.asPsiType(support, TypeMappingMode.DEFAULT, this)
|
||||
} else {
|
||||
val containingDescriptor = containingDeclaration ?: return PsiType.NULL
|
||||
val mappedType = support.mapType(this) { typeMapper, sw ->
|
||||
val mappedType = support.mapType(kotlinType, this) { typeMapper, sw ->
|
||||
typeMapper.writeParameterType(sw, kotlinType, containingDescriptor)
|
||||
}
|
||||
|
||||
return if (ultraLightMethod.checkNeedToErasureParametersTypes) TypeConversionUtil.erasure(mappedType) else mappedType
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,8 +14,10 @@ import com.intellij.psi.impl.cache.ModifierFlags
|
||||
import com.intellij.psi.impl.cache.TypeInfo
|
||||
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.impl.compiled.StubBuildingVisitor.GUESSING_MAPPER
|
||||
import com.intellij.psi.impl.light.LightMethodBuilder
|
||||
import com.intellij.psi.impl.light.LightModifierList
|
||||
import com.intellij.psi.impl.light.LightParameterListBuilder
|
||||
import com.intellij.psi.util.TypeConversionUtil
|
||||
import com.intellij.util.BitUtil.isSet
|
||||
import com.intellij.util.IncorrectOperationException
|
||||
@@ -23,9 +25,7 @@ import com.intellij.util.containers.ContainerUtil
|
||||
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
|
||||
import org.jetbrains.kotlin.asJava.UltraLightClassModifierExtension
|
||||
import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration
|
||||
import org.jetbrains.kotlin.asJava.elements.KotlinLightTypeParameterListBuilder
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightAnnotationForSourceEntry
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||
import org.jetbrains.kotlin.asJava.elements.*
|
||||
import org.jetbrains.kotlin.asJava.elements.psiType
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
@@ -39,8 +39,8 @@ import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
|
||||
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
@@ -163,31 +163,95 @@ internal fun KotlinType.asPsiType(
|
||||
support: KtUltraLightSupport,
|
||||
mode: TypeMappingMode,
|
||||
psiContext: PsiElement,
|
||||
): PsiType = support.mapType(psiContext) { typeMapper, signatureWriter ->
|
||||
): PsiType = support.mapType(this, psiContext) { typeMapper, signatureWriter ->
|
||||
typeMapper.mapType(this, signatureWriter, mode)
|
||||
}
|
||||
|
||||
internal fun KtUltraLightSupport.mapType(
|
||||
// There is no other known way found to make PSI types annotated for now.
|
||||
// It seems we need for platform changes to do it more convenient way (KTIJ-141).
|
||||
private val setPsiTypeAnnotationProvider: (PsiType, TypeAnnotationProvider) -> Unit by lazyPub {
|
||||
val klass = PsiType::class.java
|
||||
val providerField = try {
|
||||
klass.getDeclaredField("myAnnotationProvider")
|
||||
.also { it.isAccessible = true }
|
||||
} catch (e: NoSuchFieldException) {
|
||||
if (ApplicationManager.getApplication().isInternal) throw e
|
||||
null
|
||||
} catch (e: SecurityException) {
|
||||
if (ApplicationManager.getApplication().isInternal) throw e
|
||||
null
|
||||
}
|
||||
|
||||
{ psiType, provider ->
|
||||
providerField?.set(psiType, provider)
|
||||
}
|
||||
}
|
||||
|
||||
private fun annotateByKotlinType(
|
||||
psiType: PsiType,
|
||||
kotlinType: KotlinType,
|
||||
psiContext: PsiElement,
|
||||
mapTypeToSignatureWriter: (KotlinTypeMapper, JvmSignatureWriter) -> Unit,
|
||||
ultraLightSupport: KtUltraLightSupport
|
||||
) {
|
||||
fun KotlinType.getAnnotationsSequence(): Sequence<List<PsiAnnotation>> =
|
||||
sequence {
|
||||
yield(annotations.mapNotNull { it.toLightAnnotation(ultraLightSupport, psiContext) })
|
||||
for (argument in arguments) {
|
||||
yieldAll(argument.type.getAnnotationsSequence())
|
||||
}
|
||||
}
|
||||
|
||||
val annotationsIterator = kotlinType.getAnnotationsSequence().iterator()
|
||||
|
||||
fun recursiveAnnotator(psiType: PsiType) {
|
||||
if (!annotationsIterator.hasNext()) return
|
||||
val typeAnnotations = annotationsIterator.next()
|
||||
|
||||
if (psiType is PsiClassType) {
|
||||
for (parameterType in psiType.parameters) {
|
||||
recursiveAnnotator(parameterType)
|
||||
}
|
||||
} else if (psiType is PsiArrayType) {
|
||||
recursiveAnnotator(psiType.componentType)
|
||||
}
|
||||
|
||||
if (typeAnnotations.isEmpty()) return
|
||||
|
||||
val provider = TypeAnnotationProvider.Static.create(typeAnnotations.toTypedArray())
|
||||
|
||||
setPsiTypeAnnotationProvider(psiType, provider)
|
||||
}
|
||||
|
||||
recursiveAnnotator(psiType)
|
||||
}
|
||||
|
||||
internal fun KtUltraLightSupport.mapType(
|
||||
kotlinType: KotlinType?,
|
||||
psiContext: PsiElement,
|
||||
mapTypeToSignatureWriter: (KotlinTypeMapper, JvmSignatureWriter) -> Unit
|
||||
): PsiType {
|
||||
val signatureWriter = BothSignatureWriter(BothSignatureWriter.Mode.SKIP_CHECKS)
|
||||
mapTypeToSignatureWriter(typeMapper, signatureWriter)
|
||||
val canonicalSignature = signatureWriter.toString()
|
||||
return createTypeFromCanonicalText(canonicalSignature, psiContext)
|
||||
return createTypeFromCanonicalText(kotlinType, canonicalSignature, psiContext)
|
||||
}
|
||||
|
||||
fun createTypeFromCanonicalText(
|
||||
private fun KtUltraLightSupport.createTypeFromCanonicalText(
|
||||
kotlinType: KotlinType?,
|
||||
canonicalSignature: String,
|
||||
psiContext: PsiElement,
|
||||
): PsiType {
|
||||
val signature = StringCharacterIterator(canonicalSignature)
|
||||
|
||||
val javaType = SignatureParsing.parseTypeString(signature, StubBuildingVisitor.GUESSING_MAPPER)
|
||||
val javaType = SignatureParsing.parseTypeString(signature, GUESSING_MAPPER)
|
||||
val typeInfo = TypeInfo.fromString(javaType, false)
|
||||
val typeText = TypeInfo.createTypeText(typeInfo) ?: return PsiType.NULL
|
||||
|
||||
val type = ClsTypeElementImpl(psiContext, typeText, '\u0000').type
|
||||
val typeElement = ClsTypeElementImpl(psiContext, typeText, '\u0000')
|
||||
val type = typeElement.type
|
||||
if (kotlinType != null) {
|
||||
annotateByKotlinType(type, kotlinType, typeElement, this)
|
||||
}
|
||||
|
||||
if (type is PsiArrayType && psiContext is KtUltraLightParameter && psiContext.isVarArgs) {
|
||||
return PsiEllipsisType(type.componentType, type.annotationProvider)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user