[FIR IDE] LC fix annotations with special sites and nullability

This commit is contained in:
Igor Yakovlev
2020-12-11 17:42:37 +03:00
parent 2e7866ca86
commit 46071c1925
12 changed files with 173 additions and 70 deletions

View File

@@ -12,7 +12,7 @@ public final class Foo /* Foo*/ {
public Foo();// .ctor()
public final /* vararg */ void nullableVararg(@org.jetbrains.annotations.Nullable() java.lang.Object...);// nullableVararg(java.lang.Object[])
public final /* vararg */ void nullableVararg(@org.jetbrains.annotations.NotNull() java.lang.Object...);// nullableVararg(java.lang.Object[])
public final int bar4();// bar4()

View File

@@ -8,9 +8,11 @@ package org.jetbrains.kotlin.idea.frontend.api.symbols.markers
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
data class ReceiverTypeAndAnnotations(val type: KtType, val annotations: List<KtAnnotationCall>)
interface KtPossibleExtensionSymbol {
val receiverTypeAndAnnotations: ReceiverTypeAndAnnotations?
val isExtension: Boolean
val receiverType: KtType?
}
val KtCallableSymbol.isExtension: Boolean

View File

@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.asJava.elements.FirLightIdentifier
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.idea.asJava.parameters.FirLightSetterParameterForSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
import org.jetbrains.kotlin.idea.util.ifTrue
import org.jetbrains.kotlin.load.java.JvmAbi.getterName
@@ -173,8 +174,9 @@ internal class FirLightAccessorMethodForSymbol(
if (propertyParameter != null) {
builder.addParameter(
FirLightParameterForSymbol(
FirLightSetterParameterForSymbol(
parameterSymbol = propertyParameter,
containingPropertySymbol = containingPropertySymbol,
containingMethod = this@FirLightAccessorMethodForSymbol
)
)

View File

@@ -0,0 +1,59 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.idea.asJava
import com.intellij.psi.*
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.asJava.elements.FirLightIdentifier
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.idea.frontend.api.symbols.*
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolKind
import org.jetbrains.kotlin.idea.util.ifTrue
import org.jetbrains.kotlin.psi.KtParameter
internal abstract class FirLightParameterBaseForSymbol(
private val parameterSymbol: KtParameterSymbol,
private val containingMethod: FirLightMethod
) : FirLightParameter(containingMethod) {
private val _name: String = parameterSymbol.name.asString()
override fun getName(): String = _name
override fun hasModifierProperty(name: String): Boolean =
modifierList.hasModifierProperty(name)
override val kotlinOrigin: KtParameter? = parameterSymbol.psi as? KtParameter
abstract override fun getModifierList(): PsiModifierList
private val _identifier: PsiIdentifier by lazyPub {
FirLightIdentifier(this, parameterSymbol)
}
protected val nullabilityType: NullabilityType get() {
val nullabilityApplicable = !containingMethod.containingClass.let { it.isAnnotationType || it.isEnum } &&
!containingMethod.hasModifierProperty(PsiModifier.PRIVATE)
return if (nullabilityApplicable) parameterSymbol.type.getTypeNullability(parameterSymbol, FirResolvePhase.TYPES)
else NullabilityType.Unknown
}
override fun getNameIdentifier(): PsiIdentifier = _identifier
private val _type by lazyPub {
val convertedType = parameterSymbol.asPsiType(this, FirResolvePhase.TYPES)
if (convertedType is PsiArrayType && parameterSymbol.isVararg) {
PsiEllipsisType(convertedType.componentType, convertedType.annotationProvider)
} else convertedType
}
override fun getType(): PsiType = _type
abstract override fun equals(other: Any?): Boolean
abstract override fun hashCode(): Int
}

View File

@@ -11,19 +11,17 @@ import com.intellij.psi.PsiModifierList
import com.intellij.psi.PsiType
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionLikeSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtAnnotatedSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.ReceiverTypeAndAnnotations
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtNamedSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtPossibleExtensionSymbol
import org.jetbrains.kotlin.idea.frontend.api.types.KtType
import org.jetbrains.kotlin.psi.KtParameter
internal class FirLightParameterForReceiver private constructor(
private val annotatedSymbol: KtAnnotatedSymbol,
type: KtType,
private val receiverTypeAndAnnotations: ReceiverTypeAndAnnotations,
private val context: KtSymbol,
methodName: String,
method: FirLightMethod
) : FirLightParameter(method) {
@@ -35,15 +33,14 @@ internal class FirLightParameterForReceiver private constructor(
): FirLightParameterForReceiver? {
if (callableSymbol !is KtNamedSymbol) return null
if (callableSymbol !is KtAnnotatedSymbol) return null
if (callableSymbol !is KtPossibleExtensionSymbol) return null
if (!callableSymbol.isExtension) return null
val receiverType = callableSymbol.receiverType ?: return null
val extensionTypeAndAnnotations = callableSymbol.receiverTypeAndAnnotations ?: return null
return FirLightParameterForReceiver(
annotatedSymbol = callableSymbol,
type = receiverType,
receiverTypeAndAnnotations = extensionTypeAndAnnotations,
context = callableSymbol,
methodName = callableSymbol.name.asString(),
method = method
)
@@ -64,11 +61,9 @@ internal class FirLightParameterForReceiver private constructor(
override val kotlinOrigin: KtParameter? = null
private val _annotations: List<PsiAnnotation> by lazyPub {
annotatedSymbol.computeAnnotations(
parent = this,
nullability = type.getTypeNullability(annotatedSymbol, FirResolvePhase.TYPES),
annotationUseSiteTarget = AnnotationUseSiteTarget.RECEIVER,
)
receiverTypeAndAnnotations.annotations.map {
FirLightAnnotationForAnnotationCall(it, this)
}
}
override fun getModifierList(): PsiModifierList = _modifierList
@@ -77,7 +72,7 @@ internal class FirLightParameterForReceiver private constructor(
}
private val _type: PsiType by lazyPub {
type.asPsiType(annotatedSymbol, method, FirResolvePhase.TYPES)
receiverTypeAndAnnotations.type.asPsiType(context, method, FirResolvePhase.TYPES)
}
override fun getType(): PsiType = _type
@@ -85,8 +80,7 @@ internal class FirLightParameterForReceiver private constructor(
override fun equals(other: Any?): Boolean =
this === other ||
(other is FirLightParameterForReceiver &&
kotlinOrigin == other.kotlinOrigin &&
annotatedSymbol == other.annotatedSymbol)
receiverTypeAndAnnotations == other.receiverTypeAndAnnotations)
override fun hashCode(): Int = kotlinOrigin.hashCode()
}

View File

@@ -5,46 +5,30 @@
package org.jetbrains.kotlin.idea.asJava
import com.intellij.psi.*
import com.intellij.psi.PsiAnnotation
import com.intellij.psi.PsiModifierList
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.asJava.elements.FirLightIdentifier
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionLikeSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtConstructorParameterSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtParameterSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolKind
import org.jetbrains.kotlin.idea.util.ifTrue
import org.jetbrains.kotlin.psi.KtParameter
internal class FirLightParameterForSymbol(
private val parameterSymbol: KtParameterSymbol,
containingMethod: FirLightMethod
) : FirLightParameter(containingMethod) {
private val _name: String = parameterSymbol.name.asString()
override fun getName(): String = _name
private val _isVarArgs: Boolean = parameterSymbol.isVararg
override fun isVarArgs() = _isVarArgs
override fun hasModifierProperty(name: String): Boolean =
modifierList.hasModifierProperty(name)
override val kotlinOrigin: KtParameter? = parameterSymbol.psi as? KtParameter
) : FirLightParameterBaseForSymbol(parameterSymbol, containingMethod) {
private val _annotations: List<PsiAnnotation> by lazyPub {
val annotationSite = (containingMethod.isConstructor && parameterSymbol.symbolKind == KtSymbolKind.MEMBER).ifTrue {
val annotationSite = (parameterSymbol is KtConstructorParameterSymbol).ifTrue {
AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER
}
val nullabilityApplicable = !containingMethod.containingClass.let { it.isAnnotationType || it.isEnum } &&
!containingMethod.hasModifierProperty(PsiModifier.PRIVATE)
val nullabilityType = if (nullabilityApplicable)
parameterSymbol.type.getTypeNullability(parameterSymbol, FirResolvePhase.TYPES)
else NullabilityType.Unknown
val nullability = if (parameterSymbol.isVararg) NullabilityType.NotNull else super.nullabilityType
parameterSymbol.computeAnnotations(
parent = this,
nullability = nullabilityType,
nullability = nullability,
annotationUseSiteTarget = annotationSite,
includeAnnotationsWithoutSite = true
)
@@ -55,21 +39,7 @@ internal class FirLightParameterForSymbol(
FirLightClassModifierList(this, emptySet(), _annotations)
}
private val _identifier: PsiIdentifier by lazyPub {
FirLightIdentifier(this, parameterSymbol)
}
override fun getNameIdentifier(): PsiIdentifier = _identifier
private val _type by lazyPub {
val convertedType = parameterSymbol.asPsiType(this, FirResolvePhase.TYPES)
if (convertedType is PsiArrayType && parameterSymbol.isVararg) {
PsiEllipsisType(convertedType.componentType, convertedType.annotationProvider)
} else convertedType
}
override fun getType(): PsiType = _type
override fun isVarArgs() = parameterSymbol.isVararg
override fun equals(other: Any?): Boolean =
this === other ||

View File

@@ -0,0 +1,51 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.idea.asJava.parameters
import com.intellij.psi.PsiAnnotation
import com.intellij.psi.PsiModifierList
import org.jetbrains.kotlin.asJava.classes.lazyPub
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.idea.asJava.*
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtParameterSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPropertySymbol
internal class FirLightSetterParameterForSymbol(
private val containingPropertySymbol: KtPropertySymbol,
private val parameterSymbol: KtParameterSymbol,
containingMethod: FirLightMethod
) : FirLightParameterBaseForSymbol(parameterSymbol, containingMethod) {
private val _annotations: List<PsiAnnotation> by lazyPub {
val annotationsFomSetter = parameterSymbol.computeAnnotations(
parent = this,
nullability = NullabilityType.Unknown,
annotationUseSiteTarget = null,
)
val annotationsFromProperty = containingPropertySymbol.computeAnnotations(
parent = this,
nullability = nullabilityType,
annotationUseSiteTarget = AnnotationUseSiteTarget.SETTER_PARAMETER,
includeAnnotationsWithoutSite = false
)
annotationsFomSetter + annotationsFromProperty
}
override fun getModifierList(): PsiModifierList = _modifierList
private val _modifierList: PsiModifierList by lazyPub {
FirLightClassModifierList(this, emptySet(), _annotations)
}
override fun isVarArgs() = false
override fun equals(other: Any?): Boolean =
this === other ||
(other is FirLightSetterParameterForSymbol && parameterSymbol == other.parameterSymbol)
override fun hashCode(): Int = kotlinOrigin.hashCode()
}

View File

@@ -18,10 +18,7 @@ import org.jetbrains.kotlin.idea.frontend.api.fir.symbols.pointers.createSignatu
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.convertAnnotation
import org.jetbrains.kotlin.idea.frontend.api.fir.utils.firRef
import org.jetbrains.kotlin.idea.frontend.api.symbols.KtFunctionSymbol
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtAnnotationCall
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtCommonSymbolModality
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolKind
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtSymbolVisibility
import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.*
import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.CanNotCreateSymbolPointerForLocalLibraryDeclarationException
import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtPsiBasedSymbolPointer
import org.jetbrains.kotlin.idea.frontend.api.symbols.pointers.KtSymbolPointer
@@ -57,7 +54,17 @@ internal class KtFirFunctionSymbol(
override val isSuspend: Boolean get() = firRef.withFir { it.isSuspend }
override val isOverride: Boolean get() = firRef.withFir { it.isOverride }
override val receiverType: KtType? by firRef.withFirAndCache(FirResolvePhase.TYPES) { fir -> fir.receiverTypeRef?.let(builder::buildKtType) }
override val receiverTypeAndAnnotations: ReceiverTypeAndAnnotations? by firRef.withFirAndCache(FirResolvePhase.TYPES) { fir ->
fir.receiverTypeRef?.let { typeRef ->
val type = builder.buildKtType(typeRef)
val annotations = typeRef.annotations.mapNotNull {
convertAnnotation(it, fir.session)
}
ReceiverTypeAndAnnotations(type, annotations)
}
}
override val isOperator: Boolean get() = firRef.withFir { it.isOperator }
override val isExternal: Boolean get() = firRef.withFir { it.isExternal }
override val isInline: Boolean get() = firRef.withFir { it.isInline }

View File

@@ -47,7 +47,17 @@ internal class KtFirKotlinPropertySymbol(
override val isVal: Boolean get() = firRef.withFir { it.isVal }
override val name: Name get() = firRef.withFir { it.name }
override val type: KtType by firRef.withFirAndCache(FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE) { fir -> builder.buildKtType(fir.returnTypeRef) }
override val receiverType: KtType? by firRef.withFirAndCache(FirResolvePhase.TYPES) { fir -> fir.receiverTypeRef?.let(builder::buildKtType) }
override val receiverTypeAndAnnotations: ReceiverTypeAndAnnotations? by firRef.withFirAndCache(FirResolvePhase.TYPES) { fir ->
fir.receiverTypeRef?.let { typeRef ->
val type = builder.buildKtType(typeRef)
val annotations = typeRef.annotations.mapNotNull {
convertAnnotation(it, fir.session)
}
ReceiverTypeAndAnnotations(type, annotations)
}
}
override val isExtension: Boolean get() = firRef.withFir { it.receiverTypeRef != null }
override val initializer: KtConstantValue? by firRef.withFirAndCache(FirResolvePhase.BODY_RESOLVE) { fir -> fir.initializer?.convertConstantExpression() }
override val symbolKind: KtSymbolKind

View File

@@ -42,7 +42,15 @@ internal class KtFirSyntheticJavaPropertySymbol(
override val isVal: Boolean get() = firRef.withFir { it.isVal }
override val name: Name get() = firRef.withFir { it.name }
override val type: KtType by firRef.withFirAndCache(FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE) { fir -> builder.buildKtType(fir.returnTypeRef) }
override val receiverType: KtType? by firRef.withFirAndCache(FirResolvePhase.TYPES) { fir -> fir.receiverTypeRef?.let(builder::buildKtType) }
override val receiverTypeAndAnnotations: ReceiverTypeAndAnnotations? by firRef.withFirAndCache(FirResolvePhase.TYPES) { fir ->
fir.receiverTypeRef?.let { typeRef ->
val type = builder.buildKtType(typeRef)
val annotations = typeRef.annotations.mapNotNull {
convertAnnotation(it, fir.session)
}
ReceiverTypeAndAnnotations(type, annotations)
}
}
override val isExtension: Boolean get() = firRef.withFir { it.receiverTypeRef != null }
override val initializer: KtConstantValue? by firRef.withFirAndCache(FirResolvePhase.BODY_RESOLVE) { fir -> fir.initializer?.convertConstantExpression() }

View File

@@ -64,7 +64,7 @@ private fun ConeClassLikeType.expandTypeAliasIfNeeded(session: FirSession): Cone
?: return this
}
private fun convertAnnotation(
internal fun convertAnnotation(
annotationCall: FirAnnotationCall,
session: FirSession
): KtFirAnnotationCall? {

View File

@@ -94,8 +94,8 @@ private fun KtCall.stringRepresentation(): String {
is KtFunctionLikeSymbol -> buildString {
append(if (this@stringValue is KtFunctionSymbol) callableIdIfNonLocal ?: name else "<constructor>")
append("(")
(this@stringValue as? KtFunctionSymbol)?.receiverType?.let { receiver ->
append("<receiver>: ${receiver.render()}")
(this@stringValue as? KtFunctionSymbol)?.receiverTypeAndAnnotations?.let { receiver ->
append("<receiver>: ${receiver.type.render()}")
if (valueParameters.isNotEmpty()) append(", ")
}
valueParameters.joinTo(this) { parameter ->