[FIR] Extract functional type kind from annotation on lambda literal
This commit is contained in:
committed by
Space Team
parent
b48751ec9c
commit
1c8587f82d
+15
-4
@@ -13,7 +13,8 @@ import org.jetbrains.kotlin.fir.declarations.utils.isSuspend
|
|||||||
import org.jetbrains.kotlin.fir.extensions.FirFunctionalTypeKindExtension
|
import org.jetbrains.kotlin.fir.extensions.FirFunctionalTypeKindExtension
|
||||||
import org.jetbrains.kotlin.fir.extensions.extensionService
|
import org.jetbrains.kotlin.fir.extensions.extensionService
|
||||||
import org.jetbrains.kotlin.fir.extensions.functionalTypeKindExtensions
|
import org.jetbrains.kotlin.fir.extensions.functionalTypeKindExtensions
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
|
||||||
class FirFunctionalTypeKindServiceImpl(private val session: FirSession) : FirFunctionalTypeKindService() {
|
class FirFunctionalTypeKindServiceImpl(private val session: FirSession) : FirFunctionalTypeKindService() {
|
||||||
@@ -49,15 +50,25 @@ class FirFunctionalTypeKindServiceImpl(private val session: FirSession) : FirFun
|
|||||||
FunctionalTypeKindExtractor(kinds)
|
FunctionalTypeKindExtractor(kinds)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun extractSingleSpecialKindForFunction(functionSymbol: FirNamedFunctionSymbol): FunctionalTypeKind? {
|
override fun extractSingleSpecialKindForFunction(functionSymbol: FirFunctionSymbol<*>): FunctionalTypeKind? {
|
||||||
if (nonReflectKindsFromExtensions.isEmpty()) {
|
if (nonReflectKindsFromExtensions.isEmpty()) {
|
||||||
return FunctionalTypeKind.SuspendFunction.takeIf { functionSymbol.isSuspend }
|
return FunctionalTypeKind.SuspendFunction.takeIf { functionSymbol.isSuspend }
|
||||||
}
|
}
|
||||||
|
|
||||||
return extractAllSpecialKindsForFunction(functionSymbol).singleOrNull()
|
return extractAllSpecialKindsForFunction(functionSymbol).singleOrNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun extractAllSpecialKindsForFunction(functionSymbol: FirNamedFunctionSymbol): List<FunctionalTypeKind> {
|
override fun extractAllSpecialKindsForFunction(functionSymbol: FirFunctionSymbol<*>): List<FunctionalTypeKind> {
|
||||||
return extractSpecialKindsImpl(functionSymbol, { isSuspend }, { resolvedAnnotationClassIds })
|
return extractSpecialKindsImpl(
|
||||||
|
functionSymbol,
|
||||||
|
{ isSuspend },
|
||||||
|
{
|
||||||
|
when (functionSymbol) {
|
||||||
|
is FirAnonymousFunctionSymbol -> functionSymbol.annotations.mapNotNull { it.toAnnotationClassId(session) }
|
||||||
|
else -> resolvedAnnotationClassIds
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun extractAllSpecialKindsForFunctionalTypeRef(typeRef: FirFunctionTypeRef): List<FunctionalTypeKind> {
|
override fun extractAllSpecialKindsForFunctionalTypeRef(typeRef: FirFunctionTypeRef): List<FunctionalTypeKind> {
|
||||||
|
|||||||
@@ -18,10 +18,7 @@ import org.jetbrains.kotlin.fir.declarations.utils.canNarrowDownGetterType
|
|||||||
import org.jetbrains.kotlin.fir.declarations.utils.expandedConeType
|
import org.jetbrains.kotlin.fir.declarations.utils.expandedConeType
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isFinal
|
import org.jetbrains.kotlin.fir.declarations.utils.isFinal
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.modality
|
import org.jetbrains.kotlin.fir.declarations.utils.modality
|
||||||
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
import org.jetbrains.kotlin.fir.diagnostics.*
|
||||||
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
|
|
||||||
import org.jetbrains.kotlin.fir.diagnostics.ConeStubDiagnostic
|
|
||||||
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
|
|
||||||
import org.jetbrains.kotlin.fir.expressions.*
|
import org.jetbrains.kotlin.fir.expressions.*
|
||||||
import org.jetbrains.kotlin.fir.expressions.builder.*
|
import org.jetbrains.kotlin.fir.expressions.builder.*
|
||||||
import org.jetbrains.kotlin.fir.expressions.impl.FirUnitExpression
|
import org.jetbrains.kotlin.fir.expressions.impl.FirUnitExpression
|
||||||
@@ -119,10 +116,30 @@ fun FirFunction.constructFunctionalType(kind: FunctionalTypeKind? = null): ConeL
|
|||||||
/**
|
/**
|
||||||
* [kind] == null means that [FunctionalTypeKind.Function] will be used
|
* [kind] == null means that [FunctionalTypeKind.Function] will be used
|
||||||
*/
|
*/
|
||||||
fun FirFunction.constructFunctionalTypeRef(kind: FunctionalTypeKind? = null): FirResolvedTypeRef {
|
fun FirAnonymousFunction.constructFunctionalTypeRef(session: FirSession, kind: FunctionalTypeKind? = null): FirResolvedTypeRef {
|
||||||
return buildResolvedTypeRef {
|
var diagnostic: ConeDiagnostic? = null
|
||||||
source = this@constructFunctionalTypeRef.source?.fakeElement(KtFakeSourceElementKind.ImplicitTypeRef)
|
val kinds = session.functionalTypeService.extractAllSpecialKindsForFunction(symbol)
|
||||||
type = constructFunctionalType(kind)
|
val kindFromDeclaration = when(kinds.size) {
|
||||||
|
0 -> null
|
||||||
|
1 -> kinds.single()
|
||||||
|
else -> {
|
||||||
|
diagnostic = ConeAmbiguousFunctionalTypeKinds(kinds)
|
||||||
|
FunctionalTypeKind.Function
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val type = constructFunctionalType(kindFromDeclaration ?: kind)
|
||||||
|
val source = this@constructFunctionalTypeRef.source?.fakeElement(KtFakeSourceElementKind.ImplicitTypeRef)
|
||||||
|
return if (diagnostic == null) {
|
||||||
|
buildResolvedTypeRef {
|
||||||
|
this.source = source
|
||||||
|
this.type = type
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
buildErrorTypeRef {
|
||||||
|
this.source = source
|
||||||
|
this.type = type
|
||||||
|
this.diagnostic = diagnostic
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -37,6 +37,7 @@ fun extractLambdaInfoFromFunctionalType(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
val expectedFunctionalKind = expectedType.functionalTypeKind(session) ?: return null
|
val expectedFunctionalKind = expectedType.functionalTypeKind(session) ?: return null
|
||||||
|
val actualFunctionalKind = session.functionalTypeService.extractSingleSpecialKindForFunction(argument.symbol)
|
||||||
|
|
||||||
val singleStatement = argument.body?.statements?.singleOrNull() as? FirReturnExpression
|
val singleStatement = argument.body?.statements?.singleOrNull() as? FirReturnExpression
|
||||||
if (argument.returnType == null && singleStatement != null &&
|
if (argument.returnType == null && singleStatement != null &&
|
||||||
@@ -100,7 +101,7 @@ fun extractLambdaInfoFromFunctionalType(
|
|||||||
return ResolvedLambdaAtom(
|
return ResolvedLambdaAtom(
|
||||||
argument,
|
argument,
|
||||||
expectedType,
|
expectedType,
|
||||||
expectedFunctionalKind,
|
actualFunctionalKind ?: expectedFunctionalKind,
|
||||||
receiverType,
|
receiverType,
|
||||||
contextReceivers,
|
contextReceivers,
|
||||||
parameters,
|
parameters,
|
||||||
|
|||||||
+1
-1
@@ -619,7 +619,7 @@ class FirCallCompletionResultsWriterTransformer(
|
|||||||
if (needUpdateLambdaType) {
|
if (needUpdateLambdaType) {
|
||||||
val kind = expectedType?.functionalTypeKind(session)
|
val kind = expectedType?.functionalTypeKind(session)
|
||||||
?: result.typeRef.coneTypeSafe<ConeClassLikeType>()?.functionalTypeKind(session)
|
?: result.typeRef.coneTypeSafe<ConeClassLikeType>()?.functionalTypeKind(session)
|
||||||
result.replaceTypeRef(result.constructFunctionalTypeRef(kind))
|
result.replaceTypeRef(result.constructFunctionalTypeRef(session, kind))
|
||||||
session.lookupTracker?.recordTypeResolveAsLookup(result.typeRef, result.source, context.file.source)
|
session.lookupTracker?.recordTypeResolveAsLookup(result.typeRef, result.source, context.file.source)
|
||||||
}
|
}
|
||||||
// Have to delay this until the type is written to avoid adding a return if the type is Unit.
|
// Have to delay this until the type is written to avoid adding a return if the type is Unit.
|
||||||
|
|||||||
+2
-1
@@ -714,6 +714,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirAbstractBodyResolve
|
|||||||
data: ResolutionMode
|
data: ResolutionMode
|
||||||
): FirStatement = whileAnalysing(session, anonymousFunction) {
|
): FirStatement = whileAnalysing(session, anonymousFunction) {
|
||||||
// Either ContextDependent, ContextIndependent or WithExpectedType could be here
|
// Either ContextDependent, ContextIndependent or WithExpectedType could be here
|
||||||
|
anonymousFunction.transformAnnotations(transformer, ResolutionMode.ContextIndependent)
|
||||||
if (data !is ResolutionMode.LambdaResolution) {
|
if (data !is ResolutionMode.LambdaResolution) {
|
||||||
anonymousFunction.transformReturnTypeRef(transformer, ResolutionMode.ContextIndependent)
|
anonymousFunction.transformReturnTypeRef(transformer, ResolutionMode.ContextIndependent)
|
||||||
anonymousFunction.transformReceiverParameter(transformer, ResolutionMode.ContextIndependent)
|
anonymousFunction.transformReceiverParameter(transformer, ResolutionMode.ContextIndependent)
|
||||||
@@ -805,7 +806,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirAbstractBodyResolve
|
|||||||
session.lookupTracker?.recordTypeResolveAsLookup(lambda.returnTypeRef, lambda.source, context.file.source)
|
session.lookupTracker?.recordTypeResolveAsLookup(lambda.returnTypeRef, lambda.source, context.file.source)
|
||||||
}
|
}
|
||||||
|
|
||||||
lambda.replaceTypeRef(lambda.constructFunctionalTypeRef(resolvedLambdaAtom?.expectedFunctionalTypeKind))
|
lambda.replaceTypeRef(lambda.constructFunctionalTypeRef(session, resolvedLambdaAtom?.expectedFunctionalTypeKind))
|
||||||
session.lookupTracker?.recordTypeResolveAsLookup(lambda.typeRef, lambda.source, context.file.source)
|
session.lookupTracker?.recordTypeResolveAsLookup(lambda.typeRef, lambda.source, context.file.source)
|
||||||
lambda.addReturnToLastStatementIfNeeded()
|
lambda.addReturnToLastStatementIfNeeded()
|
||||||
return lambda
|
return lambda
|
||||||
|
|||||||
+2
-4
@@ -10,7 +10,6 @@ import org.jetbrains.kotlin.builtins.functions.FunctionalTypeKindExtractor
|
|||||||
import org.jetbrains.kotlin.fir.FirSession
|
import org.jetbrains.kotlin.fir.FirSession
|
||||||
import org.jetbrains.kotlin.fir.FirSessionComponent
|
import org.jetbrains.kotlin.fir.FirSessionComponent
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
|
||||||
abstract class FirFunctionalTypeKindService : FirSessionComponent {
|
abstract class FirFunctionalTypeKindService : FirSessionComponent {
|
||||||
@@ -24,9 +23,8 @@ abstract class FirFunctionalTypeKindService : FirSessionComponent {
|
|||||||
return extractor.hasKindWithSpecificPackage(packageFqName)
|
return extractor.hasKindWithSpecificPackage(packageFqName)
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract fun extractSingleSpecialKindForFunction(functionSymbol: FirNamedFunctionSymbol): FunctionalTypeKind?
|
abstract fun extractSingleSpecialKindForFunction(functionSymbol: FirFunctionSymbol<*>): FunctionalTypeKind?
|
||||||
abstract fun extractAllSpecialKindsForFunction(functionSymbol: FirNamedFunctionSymbol): List<FunctionalTypeKind>
|
abstract fun extractAllSpecialKindsForFunction(functionSymbol: FirFunctionSymbol<*>): List<FunctionalTypeKind>
|
||||||
|
|
||||||
abstract fun extractAllSpecialKindsForFunctionalTypeRef(typeRef: FirFunctionTypeRef): List<FunctionalTypeKind>
|
abstract fun extractAllSpecialKindsForFunctionalTypeRef(typeRef: FirFunctionTypeRef): List<FunctionalTypeKind>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user