FIR/Analysis API: Get parameter name from function type notation or
`@ParameterName` annotation, which is also now added during type resolution.
This commit is contained in:
committed by
Dmitriy Novozhilov
parent
afb68d15d6
commit
167dc81d3b
+3
-3
@@ -1,9 +1,9 @@
|
||||
FILE: lambda.kt
|
||||
public final fun f(t: R|(kotlin/Int) -> kotlin/Unit|): R|kotlin/Unit| {
|
||||
Int(1).R|kotlin/run|<R|kotlin/Int|, R|kotlin/Unit|>(R|<local>/t|)
|
||||
public final fun f(t: R|(@R|kotlin/ParameterName|(name = String(v)) kotlin/Int) -> kotlin/Unit|): R|kotlin/Unit| {
|
||||
Int(1).R|kotlin/run|<R|@R|kotlin/ParameterName|(name = String(v)) kotlin/Int|, R|kotlin/Unit|>(R|<local>/t|)
|
||||
}
|
||||
public final fun main(): R|kotlin/Unit| {
|
||||
R|/f|(<L> = f@fun <anonymous>(i: R|kotlin/Int|): R|kotlin/Unit| <inline=NoInline> {
|
||||
R|/f|(<L> = f@fun <anonymous>(i: R|@R|kotlin/ParameterName|(name = String(v)) kotlin/Int|): R|kotlin/Unit| <inline=NoInline> {
|
||||
^@f Unit
|
||||
}
|
||||
)
|
||||
|
||||
@@ -5,16 +5,13 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.resolve
|
||||
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.builtins.functions.FunctionClassKind
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.canNarrowDownGetterType
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.expandedConeType
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isFinal
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isInner
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isLocal
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.*
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeStubDiagnostic
|
||||
@@ -47,12 +44,49 @@ import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
||||
import org.jetbrains.kotlin.name.*
|
||||
import org.jetbrains.kotlin.resolve.ForbiddenNamedArgumentsTarget
|
||||
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||
import org.jetbrains.kotlin.types.ConstantValueKind
|
||||
import org.jetbrains.kotlin.types.SmartcastStability
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
fun List<FirQualifierPart>.toTypeProjections(): Array<ConeTypeProjection> =
|
||||
asReversed().flatMap { it.typeArgumentList.typeArguments.map { typeArgument -> typeArgument.toConeTypeProjection() } }.toTypedArray()
|
||||
|
||||
fun ConeKotlinType.withParameterNameAnnotation(valueParameter: FirValueParameter, context: ConeTypeContext): ConeKotlinType {
|
||||
if (valueParameter.name == SpecialNames.NO_NAME_PROVIDED || valueParameter.name == SpecialNames.UNDERSCORE_FOR_UNUSED_VAR) return this
|
||||
// Existing @ParameterName annotation takes precedence
|
||||
if (attributes.customAnnotations.getAnnotationsByClassId(StandardNames.FqNames.parameterNameClassId).isNotEmpty()) return this
|
||||
|
||||
val fakeSource = valueParameter.source?.fakeElement(FirFakeSourceElementKind.ParameterNameAnnotationCall)
|
||||
val parameterNameAnnotationCall = buildAnnotation {
|
||||
source = fakeSource
|
||||
annotationTypeRef =
|
||||
buildResolvedTypeRef {
|
||||
source = fakeSource
|
||||
type = ConeClassLikeTypeImpl(
|
||||
ConeClassLikeLookupTagImpl(StandardNames.FqNames.parameterNameClassId),
|
||||
emptyArray(),
|
||||
isNullable = false
|
||||
)
|
||||
}
|
||||
argumentMapping = buildAnnotationArgumentMapping {
|
||||
mapping[StandardClassIds.Annotations.ParameterNames.parameterNameName] =
|
||||
buildConstExpression(fakeSource, ConstantValueKind.String, valueParameter.name.asString(), setType = true)
|
||||
}
|
||||
}
|
||||
val attributesWithParameterNameAnnotation =
|
||||
ConeAttributes.create(listOf(CustomAnnotationTypeAttribute(listOf(parameterNameAnnotationCall))))
|
||||
return withCombinedCustomAttributesFrom(attributesWithParameterNameAnnotation, context)
|
||||
}
|
||||
|
||||
fun ConeKotlinType.withCombinedCustomAttributesFrom(other: ConeKotlinType, context: ConeTypeContext): ConeKotlinType =
|
||||
withCombinedCustomAttributesFrom(other.attributes, context)
|
||||
|
||||
private fun ConeKotlinType.withCombinedCustomAttributesFrom(other: ConeAttributes, context: ConeTypeContext): ConeKotlinType {
|
||||
val customAttributesFromOther = other.custom ?: return this
|
||||
val combinedConeAttributes = attributes.add(ConeAttributes.create(listOf(customAttributesFromOther)))
|
||||
return withAttributes(combinedConeAttributes, context)
|
||||
}
|
||||
|
||||
fun FirFunction.constructFunctionalType(isSuspend: Boolean = false): ConeLookupTagBasedType {
|
||||
val receiverTypeRef = when (this) {
|
||||
is FirSimpleFunction -> receiverTypeRef
|
||||
@@ -446,9 +480,10 @@ private fun initialTypeOfCandidate(candidate: Candidate, typeRef: FirResolvedTyp
|
||||
return candidate.substitutor.substituteOrSelf(typeRef.type)
|
||||
}
|
||||
|
||||
fun FirCallableDeclaration.getContainingClass(session: FirSession): FirRegularClass? = this.containingClass()?.let { lookupTag ->
|
||||
session.symbolProvider.getSymbolByLookupTag(lookupTag)?.fir as? FirRegularClass
|
||||
}
|
||||
fun FirCallableDeclaration.getContainingClass(session: FirSession): FirRegularClass? =
|
||||
this.containingClass()?.let { lookupTag ->
|
||||
session.symbolProvider.getSymbolByLookupTag(lookupTag)?.fir as? FirRegularClass
|
||||
}
|
||||
|
||||
fun FirFunction.getAsForbiddenNamedArgumentsTarget(session: FirSession): ForbiddenNamedArgumentsTarget? {
|
||||
if (this is FirConstructor && this.isPrimary) {
|
||||
|
||||
+2
-5
@@ -5,9 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.resolve.providers.impl
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.ThreadSafeMutableState
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.declarations.FirEnumEntry
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirOuterClassTypeParameterRef
|
||||
@@ -16,7 +14,6 @@ import org.jetbrains.kotlin.fir.declarations.utils.isLocal
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeUnexpectedTypeArgumentsError
|
||||
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeOuterClassArgumentsRequired
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedQualifierError
|
||||
@@ -348,7 +345,7 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
|
||||
private fun createFunctionalType(typeRef: FirFunctionTypeRef): ConeClassLikeType {
|
||||
val parameters =
|
||||
listOfNotNull(typeRef.receiverTypeRef?.coneType) +
|
||||
typeRef.valueParameters.map { it.returnTypeRef.coneType } +
|
||||
typeRef.valueParameters.map { it.returnTypeRef.coneType.withParameterNameAnnotation(it, session.typeContext) } +
|
||||
listOf(typeRef.returnTypeRef.coneType)
|
||||
val classId = if (typeRef.isSuspend) {
|
||||
StandardClassIds.SuspendFunctionN(typeRef.parametersCount)
|
||||
|
||||
+6
-2
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.resolve.substitution
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.inferenceComponents
|
||||
import org.jetbrains.kotlin.fir.resolve.withCombinedCustomAttributesFrom
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.fir.typeContext
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
@@ -164,7 +165,10 @@ data class ConeSubstitutorByMap(
|
||||
) : AbstractConeSubstitutor(useSiteSession.typeContext) {
|
||||
override fun substituteType(type: ConeKotlinType): ConeKotlinType? {
|
||||
if (type !is ConeTypeParameterType) return null
|
||||
val result = substitution[type.lookupTag.symbol].updateNullabilityIfNeeded(type) ?: return null
|
||||
val result =
|
||||
substitution[type.lookupTag.symbol].updateNullabilityIfNeeded(type)
|
||||
?.withCombinedCustomAttributesFrom(type, useSiteSession.typeContext)
|
||||
?: return null
|
||||
if (type.isUnsafeVarianceType(useSiteSession)) {
|
||||
return useSiteSession.inferenceComponents.approximator.approximateToSuperType(
|
||||
result, TypeApproximatorConfiguration.FinalApproximationAfterResolutionAndInference
|
||||
@@ -180,7 +184,7 @@ fun createTypeSubstitutorByTypeConstructor(map: Map<TypeConstructorMarker, ConeK
|
||||
override fun substituteType(type: ConeKotlinType): ConeKotlinType? {
|
||||
if (type !is ConeLookupTagBasedType && type !is ConeStubType) return null
|
||||
val new = map[type.typeConstructor(context)] ?: return null
|
||||
return new.approximateIntegerLiteralType().updateNullabilityIfNeeded(type)
|
||||
return new.approximateIntegerLiteralType().updateNullabilityIfNeeded(type)?.withCombinedCustomAttributesFrom(type, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,6 +183,11 @@ sealed class FirFakeSourceElementKind : FirSourceElementKind() {
|
||||
|
||||
// for annotation moved to another element due to annotation use-site target
|
||||
object FromUseSiteTarget : FirFakeSourceElementKind()
|
||||
|
||||
// for `@ParameterName` annotation call added to function types with names in the notation
|
||||
// with a fake source that refers to the value parameter in the function type notation
|
||||
// e.g., `(x: Int) -> Unit` becomes `Function1<@ParameterName("x") Int, Unit>`
|
||||
object ParameterNameAnnotationCall : FirFakeSourceElementKind()
|
||||
}
|
||||
|
||||
sealed class FirSourceElement {
|
||||
|
||||
+1
-1
@@ -27,6 +27,6 @@ class CustomAnnotationTypeAttribute(val annotations: List<FirAnnotation>) : Cone
|
||||
get() = CustomAnnotationTypeAttribute::class
|
||||
}
|
||||
|
||||
private val ConeAttributes.custom: CustomAnnotationTypeAttribute? by ConeAttributes.attributeAccessor<CustomAnnotationTypeAttribute>()
|
||||
val ConeAttributes.custom: CustomAnnotationTypeAttribute? by ConeAttributes.attributeAccessor<CustomAnnotationTypeAttribute>()
|
||||
|
||||
val ConeAttributes.customAnnotations: List<FirAnnotation> get() = custom?.annotations.orEmpty()
|
||||
|
||||
Reference in New Issue
Block a user