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
+60
-9
@@ -6,29 +6,42 @@
|
||||
package org.jetbrains.kotlin.analysis.api.fir.symbols
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
||||
import org.jetbrains.kotlin.fir.renderWithType
|
||||
import org.jetbrains.kotlin.fir.types.arrayElementType
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
import org.jetbrains.kotlin.analysis.api.fir.findPsi
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirModuleResolveState
|
||||
import org.jetbrains.kotlin.analysis.api.fir.KtSymbolByFirBuilder
|
||||
import org.jetbrains.kotlin.analysis.api.fir.findPsi
|
||||
import org.jetbrains.kotlin.analysis.api.fir.symbols.annotations.KtFirAnnotationCall
|
||||
import org.jetbrains.kotlin.analysis.api.fir.symbols.annotations.containsAnnotation
|
||||
import org.jetbrains.kotlin.analysis.api.fir.symbols.annotations.getAnnotationClassIds
|
||||
import org.jetbrains.kotlin.analysis.api.fir.symbols.annotations.toAnnotationsList
|
||||
import org.jetbrains.kotlin.analysis.api.fir.utils.cached
|
||||
import org.jetbrains.kotlin.analysis.api.fir.utils.firRef
|
||||
import org.jetbrains.kotlin.analysis.api.fir.utils.weakRef
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.KtValueParameterSymbol
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtAnnotationCall
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtTypeAndAnnotations
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtPsiBasedSymbolPointer
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.pointers.KtSymbolPointer
|
||||
import org.jetbrains.kotlin.analysis.api.tokens.ValidityToken
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.FirModuleResolveState
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.getOrBuildFirOfType
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.api.withFirDeclaration
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
||||
import org.jetbrains.kotlin.fir.declarations.getAnnotationsByClassId
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
|
||||
import org.jetbrains.kotlin.fir.expressions.FirConstExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.unwrapArgument
|
||||
import org.jetbrains.kotlin.fir.psi
|
||||
import org.jetbrains.kotlin.fir.renderWithType
|
||||
import org.jetbrains.kotlin.fir.types.arrayElementType
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
import org.jetbrains.kotlin.fir.types.customAnnotations
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
internal class KtFirValueParameterSymbol(
|
||||
fir: FirValueParameter,
|
||||
@@ -39,7 +52,45 @@ internal class KtFirValueParameterSymbol(
|
||||
override val firRef = firRef(fir, resolveState)
|
||||
override val psi: PsiElement? by firRef.withFirAndCache { fir -> fir.findPsi(fir.moduleData.session) }
|
||||
|
||||
override val name: Name get() = firRef.withFir { it.name }
|
||||
override val name: Name by cached {
|
||||
firRef.withFir { fir ->
|
||||
val defaultName = fir.name
|
||||
if (fir.psi != null) return@withFir defaultName
|
||||
|
||||
// The case where PSI is null is when calling `invoke()` on a variable with functional type, e.g. `x(1)` below:
|
||||
//
|
||||
// fun foo(x: (item: Int) -> Unit) { x(1) }
|
||||
// fun bar(x: Function1<@ParameterName("item") Int, Unit>) { x(1) }
|
||||
//
|
||||
// The function being called is `invoke(p1: Int)` on `Function1<Int, Unit>` which is from the stdlib, and therefore no source
|
||||
// PSI for the function or its parameters. In that case, we use the `@ParameterName` annotation on the parameter type if present
|
||||
// and fall back to the parameter names from the `invoke()` function (`p1`, `p2`, etc.).
|
||||
//
|
||||
// Note: During type resolution, `@ParameterName` type annotations are added based on the names (which are optional) in the
|
||||
// function type notation. Therefore the `x` parameter in both example functions above have the same type and type annotations.
|
||||
fir.withFirDeclaration(resolveState, FirResolvePhase.TYPES) {
|
||||
val parameterNameAnnotation =
|
||||
fir.returnTypeRef.coneType.attributes.customAnnotations
|
||||
.getAnnotationsByClassId(StandardNames.FqNames.parameterNameClassId)
|
||||
.singleOrNull()?.safeAs<FirAnnotation>() ?: return@withFirDeclaration defaultName
|
||||
|
||||
// The parent KtDeclaration is where the variable with functional type and `@ParameterName` annotation is declared.
|
||||
val parentKtDeclaration =
|
||||
parameterNameAnnotation.psi?.getNonStrictParentOfType<KtDeclaration>() ?: return@withFirDeclaration defaultName
|
||||
val parentFirDeclaration = parentKtDeclaration.getOrBuildFirOfType<FirDeclaration>(resolveState)
|
||||
|
||||
// Resolve to ARGUMENTS_OF_ANNOTATIONS phase to get `name` argument from mapping.
|
||||
val parameterNameFromAnnotation =
|
||||
parentFirDeclaration.withFirDeclaration(resolveState, FirResolvePhase.ARGUMENTS_OF_ANNOTATIONS) {
|
||||
val nameArgument =
|
||||
parameterNameAnnotation.argumentMapping.mapping[StandardClassIds.Annotations.ParameterNames.parameterNameName]
|
||||
nameArgument?.unwrapArgument()?.safeAs<FirConstExpression<*>>()?.value as? String
|
||||
}
|
||||
parameterNameFromAnnotation?.let { Name.identifier(it) } ?: defaultName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override val isVararg: Boolean get() = firRef.withFir { it.isVararg }
|
||||
override val annotatedType: KtTypeAndAnnotations by firRef.withFirAndCache(FirResolvePhase.TYPES) { fir ->
|
||||
if (fir.isVararg) {
|
||||
|
||||
+1
@@ -91,6 +91,7 @@ private fun KtCall.stringRepresentation(): String {
|
||||
append(": ${annotatedType.type.render()}")
|
||||
}
|
||||
is KtValueParameterSymbol -> "${if (isVararg) "vararg " else ""}$name: ${annotatedType.type.render()}"
|
||||
is KtVariableSymbol -> "${if (isVal) "val" else "var"} $name: ${annotatedType.type.render()}"
|
||||
is KtSuccessCallTarget -> symbol.stringValue()
|
||||
is KtErrorCallTarget -> "ERR<${this.diagnostic.defaultMessage}, [${candidates.joinToString { it.stringValue() }}]>"
|
||||
is Boolean -> toString()
|
||||
|
||||
+36
@@ -402,6 +402,42 @@ public class ResolveCallTestGenerated extends AbstractResolveCallTest {
|
||||
runTest("analysis/analysis-api/testData/analysisSession/resolveCall/variableAsFunctionLikeCall.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("variableAsFunctionWithParameterName.kt")
|
||||
public void testVariableAsFunctionWithParameterName() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/analysisSession/resolveCall/variableAsFunctionWithParameterName.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("variableAsFunctionWithParameterNameAnnotation.kt")
|
||||
public void testVariableAsFunctionWithParameterNameAnnotation() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/analysisSession/resolveCall/variableAsFunctionWithParameterNameAnnotation.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("variableAsFunctionWithParameterNameAnnotationConflict.kt")
|
||||
public void testVariableAsFunctionWithParameterNameAnnotationConflict() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/analysisSession/resolveCall/variableAsFunctionWithParameterNameAnnotationConflict.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("variableAsFunctionWithParameterNameGeneric.kt")
|
||||
public void testVariableAsFunctionWithParameterNameGeneric() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/analysisSession/resolveCall/variableAsFunctionWithParameterNameGeneric.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("variableAsFunctionWithParameterNameInNonFunctionType.kt")
|
||||
public void testVariableAsFunctionWithParameterNameInNonFunctionType() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/analysisSession/resolveCall/variableAsFunctionWithParameterNameInNonFunctionType.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("variableAsFunctionWithParameterNameMixed.kt")
|
||||
public void testVariableAsFunctionWithParameterNameMixed() throws Exception {
|
||||
runTest("analysis/analysis-api/testData/analysisSession/resolveCall/variableAsFunctionWithParameterNameMixed.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("variableWithExtensionInvoke.kt")
|
||||
public void testVariableWithExtensionInvoke() throws Exception {
|
||||
|
||||
@@ -67,12 +67,13 @@ public sealed class KtDeclaredFunctionCall : KtCall() {
|
||||
* fun Int.invoke() {}
|
||||
*/
|
||||
public class KtVariableWithInvokeFunctionCall(
|
||||
public val target: KtVariableLikeSymbol,
|
||||
private val _target: KtVariableLikeSymbol,
|
||||
private val _argumentMapping: LinkedHashMap<KtExpression, KtValueParameterSymbol>,
|
||||
private val _targetFunction: KtCallTarget,
|
||||
private val _substitutor: KtSubstitutor,
|
||||
override val token: ValidityToken
|
||||
) : KtDeclaredFunctionCall() {
|
||||
public val target: KtVariableLikeSymbol get() = withValidityAssertion { _target }
|
||||
override val argumentMapping: LinkedHashMap<KtExpression, KtValueParameterSymbol>
|
||||
get() = withValidityAssertion { _argumentMapping }
|
||||
override val targetFunction: KtCallTarget
|
||||
|
||||
+11
@@ -138,4 +138,15 @@ public abstract class KtValueParameterSymbol : KtVariableLikeSymbol(), KtSymbolW
|
||||
public abstract val isVararg: Boolean
|
||||
|
||||
abstract override fun createPointer(): KtSymbolPointer<KtValueParameterSymbol>
|
||||
|
||||
/**
|
||||
* The name of the value parameter. For a parameter of `FunctionN.invoke()` functions, the name is taken from the function type
|
||||
* notation, if a name is present. For example:
|
||||
* ```
|
||||
* fun foo(x: (item: Int, String) -> Unit) =
|
||||
* x(1, "") // or `x.invoke(1, "")`
|
||||
* ```
|
||||
* The names of the value parameters for `invoke()` are "item" and "p2" (its default parameter name).
|
||||
*/
|
||||
abstract override val name: Name
|
||||
}
|
||||
|
||||
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
fun call(x: (a: Int, b: String) -> Unit) {
|
||||
<expr>x(1, "")</expr>
|
||||
}
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
KtFunctionalTypeVariableCall:
|
||||
target = x: kotlin.Function2<@R|kotlin.ParameterName|(name = String(a)) kotlin.Int, @R|kotlin.ParameterName|(name = String(b)) kotlin.String, kotlin.Unit>
|
||||
argumentMapping = { 1 -> (a: @R|kotlin.ParameterName|(name = String(a)) kotlin.Int), "" -> (b: @R|kotlin.ParameterName|(name = String(b)) kotlin.String) }
|
||||
targetFunction = kotlin/Function2.invoke(<dispatch receiver>: kotlin.Function2<@R|kotlin.ParameterName|(name = String(a)) kotlin.Int, @R|kotlin.ParameterName|(name = String(b)) kotlin.String, kotlin.Unit>, a: @R|kotlin.ParameterName|(name = String(a)) kotlin.Int, b: @R|kotlin.ParameterName|(name = String(b)) kotlin.String): kotlin.Unit
|
||||
substitutor = <empty substitutor>
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fun call(x: Function2<@ParameterName("a") Int, @ParameterName("b") String, Unit>) {
|
||||
<expr>x(1, "")</expr>
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
KtFunctionalTypeVariableCall:
|
||||
target = x: kotlin.Function2<@R|kotlin.ParameterName|(name = String(a)) kotlin.Int, @R|kotlin.ParameterName|(name = String(b)) kotlin.String, kotlin.Unit>
|
||||
argumentMapping = { 1 -> (a: @R|kotlin.ParameterName|(name = String(a)) kotlin.Int), "" -> (b: @R|kotlin.ParameterName|(name = String(b)) kotlin.String) }
|
||||
targetFunction = kotlin/Function2.invoke(<dispatch receiver>: kotlin.Function2<@R|kotlin.ParameterName|(name = String(a)) kotlin.Int, @R|kotlin.ParameterName|(name = String(b)) kotlin.String, kotlin.Unit>, a: @R|kotlin.ParameterName|(name = String(a)) kotlin.Int, b: @R|kotlin.ParameterName|(name = String(b)) kotlin.String): kotlin.Unit
|
||||
substitutor = <empty substitutor>
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
// @ParameterName annotation takes precedence over name in function type parameter
|
||||
fun call(x: (notMe: @ParameterName("a") Int, meNeither: @ParameterName("b") String) -> Unit) {
|
||||
<expr>x(1, "")</expr>
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
KtFunctionalTypeVariableCall:
|
||||
target = x: kotlin.Function2<@R|kotlin.ParameterName|(name = String(a)) kotlin.Int, @R|kotlin.ParameterName|(name = String(b)) kotlin.String, kotlin.Unit>
|
||||
argumentMapping = { 1 -> (a: @R|kotlin.ParameterName|(name = String(a)) kotlin.Int), "" -> (b: @R|kotlin.ParameterName|(name = String(b)) kotlin.String) }
|
||||
targetFunction = kotlin/Function2.invoke(<dispatch receiver>: kotlin.Function2<@R|kotlin.ParameterName|(name = String(a)) kotlin.Int, @R|kotlin.ParameterName|(name = String(b)) kotlin.String, kotlin.Unit>, a: @R|kotlin.ParameterName|(name = String(a)) kotlin.Int, b: @R|kotlin.ParameterName|(name = String(b)) kotlin.String): kotlin.Unit
|
||||
substitutor = <empty substitutor>
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
fun <T> T.foo(): (a: T) -> Unit = TODO()
|
||||
|
||||
fun call() {
|
||||
val x = 123.foo()
|
||||
<expr>x(1)</expr>
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
KtFunctionalTypeVariableCall:
|
||||
target = val x: kotlin.Function1<@R|kotlin.ParameterName|(name = String(a)) kotlin.Int, kotlin.Unit>
|
||||
argumentMapping = { 1 -> (a: @R|kotlin.ParameterName|(name = String(a)) kotlin.Int) }
|
||||
targetFunction = kotlin/Function1.invoke(<dispatch receiver>: kotlin.Function1<@R|kotlin.ParameterName|(name = String(a)) kotlin.Int, kotlin.Unit>, a: @R|kotlin.ParameterName|(name = String(a)) kotlin.Int): kotlin.Unit
|
||||
substitutor = <empty substitutor>
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
// @ParameterName annotation is ignored when not used in function type
|
||||
fun call(a: @ParameterName("notMe") Int, b: @ParameterName("meNeither") String) {
|
||||
<expr>call(1, "")</expr>
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
KtFunctionCall:
|
||||
argumentMapping = { 1 -> (a: @R|kotlin.ParameterName|(name = String(notMe)) kotlin.Int), "" -> (b: @R|kotlin.ParameterName|(name = String(meNeither)) kotlin.String) }
|
||||
targetFunction = /call(a: @R|kotlin.ParameterName|(name = String(notMe)) kotlin.Int, b: @R|kotlin.ParameterName|(name = String(meNeither)) kotlin.String): kotlin.Unit
|
||||
substitutor = <empty substitutor>
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fun call(x: (a: Int, String) -> Unit) {
|
||||
<expr>x(1, "")</expr>
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
KtFunctionalTypeVariableCall:
|
||||
target = x: kotlin.Function2<@R|kotlin.ParameterName|(name = String(a)) kotlin.Int, kotlin.String, kotlin.Unit>
|
||||
argumentMapping = { 1 -> (a: @R|kotlin.ParameterName|(name = String(a)) kotlin.Int), "" -> (p2: kotlin.String) }
|
||||
targetFunction = kotlin/Function2.invoke(<dispatch receiver>: kotlin.Function2<@R|kotlin.ParameterName|(name = String(a)) kotlin.Int, kotlin.String, kotlin.Unit>, a: @R|kotlin.ParameterName|(name = String(a)) kotlin.Int, p2: kotlin.String): kotlin.Unit
|
||||
substitutor = <empty substitutor>
|
||||
+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()
|
||||
|
||||
+47
-47
@@ -26,12 +26,12 @@ FILE fqName:<root> fileName:/castsInsideCoroutineInference.kt
|
||||
$this: GET_VAR 'block: @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction2<<root>.CoroutineScope, <root>.FlowCollector<R of <root>.scopedFlow>, kotlin.Unit> declared in <root>.scopedFlow' type=@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction2<<root>.CoroutineScope, <root>.FlowCollector<R of <root>.scopedFlow>, kotlin.Unit> origin=VARIABLE_AS_FUNCTION
|
||||
p1: GET_VAR '<this>: <root>.CoroutineScope declared in <root>.scopedFlow.<anonymous>.<anonymous>' type=<root>.CoroutineScope origin=null
|
||||
p2: GET_VAR 'val collector: <root>.FlowCollector<R of <root>.scopedFlow> [val] declared in <root>.scopedFlow.<anonymous>' type=<root>.FlowCollector<R of <root>.scopedFlow> origin=null
|
||||
FUN name:onCompletion visibility:public modality:FINAL <T> ($receiver:<root>.Flow<T of <root>.onCompletion>, action:@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction2<<root>.FlowCollector<T of <root>.onCompletion>, kotlin.Throwable?, kotlin.Unit>) returnType:<root>.Flow<T of <root>.onCompletion>
|
||||
FUN name:onCompletion visibility:public modality:FINAL <T> ($receiver:<root>.Flow<T of <root>.onCompletion>, action:@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction2<<root>.FlowCollector<T of <root>.onCompletion>, @[ParameterName(name = 'cause')] kotlin.Throwable?, kotlin.Unit>) returnType:<root>.Flow<T of <root>.onCompletion>
|
||||
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?]
|
||||
$receiver: VALUE_PARAMETER name:<this> type:<root>.Flow<T of <root>.onCompletion>
|
||||
VALUE_PARAMETER name:action index:0 type:@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction2<<root>.FlowCollector<T of <root>.onCompletion>, kotlin.Throwable?, kotlin.Unit>
|
||||
VALUE_PARAMETER name:action index:0 type:@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction2<<root>.FlowCollector<T of <root>.onCompletion>, @[ParameterName(name = 'cause')] kotlin.Throwable?, kotlin.Unit>
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun onCompletion <T> (action: @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction2<<root>.FlowCollector<T of <root>.onCompletion>, kotlin.Throwable?, kotlin.Unit>): <root>.Flow<T of <root>.onCompletion> declared in <root>'
|
||||
RETURN type=kotlin.Nothing from='public final fun onCompletion <T> (action: @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction2<<root>.FlowCollector<T of <root>.onCompletion>, @[ParameterName(name = 'cause')] kotlin.Throwable?, kotlin.Unit>): <root>.Flow<T of <root>.onCompletion> declared in <root>'
|
||||
CALL 'public final fun unsafeFlow <T> (block: @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<<root>.FlowCollector<T of <root>.unsafeFlow>, kotlin.Unit>): <root>.Flow<T of <root>.unsafeFlow> [inline] declared in <root>' type=<root>.Flow<T of <root>.onCompletion> origin=null
|
||||
<T>: T of <root>.onCompletion
|
||||
block: FUN_EXPR type=kotlin.coroutines.SuspendFunction1<<root>.FlowCollector<T of <root>.onCompletion>, kotlin.Unit> origin=LAMBDA
|
||||
@@ -42,14 +42,14 @@ FILE fqName:<root> fileName:/castsInsideCoroutineInference.kt
|
||||
CONSTRUCTOR_CALL 'public constructor <init> (collector: <root>.FlowCollector<T of <root>.SafeCollector>) [primary] declared in <root>.SafeCollector' type=<root>.SafeCollector<T of <root>.onCompletion> origin=null
|
||||
<class: T>: T of <root>.onCompletion
|
||||
collector: GET_VAR '<this>: <root>.FlowCollector<T of <root>.onCompletion> declared in <root>.onCompletion.<anonymous>' type=<root>.FlowCollector<T of <root>.onCompletion> origin=null
|
||||
CALL 'public final fun invokeSafely <T> (action: @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction2<<root>.FlowCollector<T of <root>.invokeSafely>, kotlin.Throwable?, kotlin.Unit>): kotlin.Unit [suspend] declared in <root>' type=kotlin.Unit origin=null
|
||||
CALL 'public final fun invokeSafely <T> (action: @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction2<<root>.FlowCollector<T of <root>.invokeSafely>, @[ParameterName(name = 'cause')] kotlin.Throwable?, kotlin.Unit>): kotlin.Unit [suspend] declared in <root>' type=kotlin.Unit origin=null
|
||||
<T>: T of <root>.onCompletion
|
||||
$receiver: GET_VAR 'val safeCollector: <root>.SafeCollector<T of <root>.onCompletion> [val] declared in <root>.onCompletion.<anonymous>' type=<root>.SafeCollector<T of <root>.onCompletion> origin=null
|
||||
action: GET_VAR 'action: @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction2<<root>.FlowCollector<T of <root>.onCompletion>, kotlin.Throwable?, kotlin.Unit> declared in <root>.onCompletion' type=@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction2<<root>.FlowCollector<T of <root>.onCompletion>, kotlin.Throwable?, kotlin.Unit> origin=null
|
||||
FUN name:invokeSafely visibility:public modality:FINAL <T> ($receiver:<root>.FlowCollector<T of <root>.invokeSafely>, action:@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction2<<root>.FlowCollector<T of <root>.invokeSafely>, kotlin.Throwable?, kotlin.Unit>) returnType:kotlin.Unit [suspend]
|
||||
action: GET_VAR 'action: @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction2<<root>.FlowCollector<T of <root>.onCompletion>, @[ParameterName(name = 'cause')] kotlin.Throwable?, kotlin.Unit> declared in <root>.onCompletion' type=@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction2<<root>.FlowCollector<T of <root>.onCompletion>, @[ParameterName(name = 'cause')] kotlin.Throwable?, kotlin.Unit> origin=null
|
||||
FUN name:invokeSafely visibility:public modality:FINAL <T> ($receiver:<root>.FlowCollector<T of <root>.invokeSafely>, action:@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction2<<root>.FlowCollector<T of <root>.invokeSafely>, @[ParameterName(name = 'cause')] kotlin.Throwable?, kotlin.Unit>) returnType:kotlin.Unit [suspend]
|
||||
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?]
|
||||
$receiver: VALUE_PARAMETER name:<this> type:<root>.FlowCollector<T of <root>.invokeSafely>
|
||||
VALUE_PARAMETER name:action index:0 type:@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction2<<root>.FlowCollector<T of <root>.invokeSafely>, kotlin.Throwable?, kotlin.Unit>
|
||||
VALUE_PARAMETER name:action index:0 type:@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction2<<root>.FlowCollector<T of <root>.invokeSafely>, @[ParameterName(name = 'cause')] kotlin.Throwable?, kotlin.Unit>
|
||||
BLOCK_BODY
|
||||
FUN name:unsafeFlow visibility:public modality:FINAL <T> (block:@[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<<root>.FlowCollector<T of <root>.unsafeFlow>, kotlin.Unit>) returnType:<root>.Flow<T of <root>.unsafeFlow> [inline]
|
||||
annotations:
|
||||
@@ -61,25 +61,25 @@ FILE fqName:<root> fileName:/castsInsideCoroutineInference.kt
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun unsafeFlow <T> (block: @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<<root>.FlowCollector<T of <root>.unsafeFlow>, kotlin.Unit>): <root>.Flow<T of <root>.unsafeFlow> [inline] declared in <root>'
|
||||
CALL 'public final fun TODO (): kotlin.Nothing [inline] declared in kotlin.StandardKt' type=kotlin.Nothing origin=null
|
||||
FUN name:onCompletion visibility:public modality:FINAL <T> ($receiver:<root>.Flow<T of <root>.onCompletion>, action:kotlin.coroutines.SuspendFunction1<kotlin.Throwable?, kotlin.Unit>) returnType:<root>.Flow<T of <root>.onCompletion>
|
||||
FUN name:onCompletion visibility:public modality:FINAL <T> ($receiver:<root>.Flow<T of <root>.onCompletion>, action:kotlin.coroutines.SuspendFunction1<@[ParameterName(name = 'cause')] kotlin.Throwable?, kotlin.Unit>) returnType:<root>.Flow<T of <root>.onCompletion>
|
||||
annotations:
|
||||
Deprecated(message = 'binary compatibility with a version w/o FlowCollector receiver', replaceWith = <null>, level = GET_ENUM 'ENUM_ENTRY IR_EXTERNAL_DECLARATION_STUB name:HIDDEN' type=kotlin.DeprecationLevel)
|
||||
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?]
|
||||
$receiver: VALUE_PARAMETER name:<this> type:<root>.Flow<T of <root>.onCompletion>
|
||||
VALUE_PARAMETER name:action index:0 type:kotlin.coroutines.SuspendFunction1<kotlin.Throwable?, kotlin.Unit>
|
||||
VALUE_PARAMETER name:action index:0 type:kotlin.coroutines.SuspendFunction1<@[ParameterName(name = 'cause')] kotlin.Throwable?, kotlin.Unit>
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun onCompletion <T> (action: kotlin.coroutines.SuspendFunction1<kotlin.Throwable?, kotlin.Unit>): <root>.Flow<T of <root>.onCompletion> declared in <root>'
|
||||
CALL 'public final fun onCompletion <T> (action: @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction2<<root>.FlowCollector<T of <root>.onCompletion>, kotlin.Throwable?, kotlin.Unit>): <root>.Flow<T of <root>.onCompletion> declared in <root>' type=<root>.Flow<T of <root>.onCompletion> origin=null
|
||||
RETURN type=kotlin.Nothing from='public final fun onCompletion <T> (action: kotlin.coroutines.SuspendFunction1<@[ParameterName(name = 'cause')] kotlin.Throwable?, kotlin.Unit>): <root>.Flow<T of <root>.onCompletion> declared in <root>'
|
||||
CALL 'public final fun onCompletion <T> (action: @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction2<<root>.FlowCollector<T of <root>.onCompletion>, @[ParameterName(name = 'cause')] kotlin.Throwable?, kotlin.Unit>): <root>.Flow<T of <root>.onCompletion> declared in <root>' type=<root>.Flow<T of <root>.onCompletion> origin=null
|
||||
<T>: T of <root>.onCompletion
|
||||
$receiver: GET_VAR '<this>: <root>.Flow<T of <root>.onCompletion> declared in <root>.onCompletion' type=<root>.Flow<T of <root>.onCompletion> origin=null
|
||||
action: FUN_EXPR type=kotlin.coroutines.SuspendFunction2<<root>.FlowCollector<T of <root>.onCompletion>, kotlin.Throwable?, kotlin.Unit> origin=LAMBDA
|
||||
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> ($receiver:<root>.FlowCollector<T of <root>.onCompletion>, it:kotlin.Throwable?) returnType:kotlin.Unit [suspend]
|
||||
action: FUN_EXPR type=kotlin.coroutines.SuspendFunction2<<root>.FlowCollector<T of <root>.onCompletion>, @[ParameterName(name = 'cause')] kotlin.Throwable?, kotlin.Unit> origin=LAMBDA
|
||||
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> ($receiver:<root>.FlowCollector<T of <root>.onCompletion>, it:@[ParameterName(name = 'cause')] kotlin.Throwable?) returnType:kotlin.Unit [suspend]
|
||||
$receiver: VALUE_PARAMETER name:<this> type:<root>.FlowCollector<T of <root>.onCompletion>
|
||||
VALUE_PARAMETER name:it index:0 type:kotlin.Throwable?
|
||||
VALUE_PARAMETER name:it index:0 type:@[ParameterName(name = 'cause')] kotlin.Throwable?
|
||||
BLOCK_BODY
|
||||
CALL 'public abstract fun invoke (p1: P1 of kotlin.coroutines.SuspendFunction1): R of kotlin.coroutines.SuspendFunction1 [suspend,operator] declared in kotlin.coroutines.SuspendFunction1' type=kotlin.Unit origin=null
|
||||
$this: GET_VAR 'action: kotlin.coroutines.SuspendFunction1<kotlin.Throwable?, kotlin.Unit> declared in <root>.onCompletion' type=kotlin.coroutines.SuspendFunction1<kotlin.Throwable?, kotlin.Unit> origin=VARIABLE_AS_FUNCTION
|
||||
p1: GET_VAR 'it: kotlin.Throwable? declared in <root>.onCompletion.<anonymous>' type=kotlin.Throwable? origin=null
|
||||
$this: GET_VAR 'action: kotlin.coroutines.SuspendFunction1<@[ParameterName(name = 'cause')] kotlin.Throwable?, kotlin.Unit> declared in <root>.onCompletion' type=kotlin.coroutines.SuspendFunction1<@[ParameterName(name = 'cause')] kotlin.Throwable?, kotlin.Unit> origin=VARIABLE_AS_FUNCTION
|
||||
p1: GET_VAR 'it: @[ParameterName(name = 'cause')] kotlin.Throwable? declared in <root>.onCompletion.<anonymous>' type=@[ParameterName(name = 'cause')] kotlin.Throwable? origin=null
|
||||
FUN name:asFairChannel visibility:private modality:FINAL <> ($receiver:<root>.CoroutineScope, flow:<root>.Flow<*>) returnType:<root>.ReceiveChannel<kotlin.Any>
|
||||
$receiver: VALUE_PARAMETER name:<this> type:<root>.CoroutineScope
|
||||
VALUE_PARAMETER name:flow index:0 type:<root>.Flow<*>
|
||||
@@ -96,63 +96,63 @@ FILE fqName:<root> fileName:/castsInsideCoroutineInference.kt
|
||||
TYPE_OP type=<root>.ChannelCoroutine<kotlin.Any> origin=CAST typeOperand=<root>.ChannelCoroutine<kotlin.Any>
|
||||
CALL 'public abstract fun <get-channel> (): <root>.SendChannel<E of <root>.ProducerScope> declared in <root>.ProducerScope' type=<root>.SendChannel<kotlin.Nothing> origin=GET_PROPERTY
|
||||
$this: GET_VAR '<this>: <root>.ProducerScope<kotlin.Any> declared in <root>.asFairChannel.<anonymous>' type=<root>.ProducerScope<kotlin.Nothing> origin=null
|
||||
CALL 'public final fun collect <T> (action: kotlin.coroutines.SuspendFunction1<T of <root>.collect, kotlin.Unit>): kotlin.Unit [inline,suspend] declared in <root>' type=kotlin.Unit origin=null
|
||||
CALL 'public final fun collect <T> (action: kotlin.coroutines.SuspendFunction1<@[ParameterName(name = 'value')] T of <root>.collect, kotlin.Unit>): kotlin.Unit [inline,suspend] declared in <root>' type=kotlin.Unit origin=null
|
||||
<T>: kotlin.Any?
|
||||
$receiver: GET_VAR 'flow: <root>.Flow<*> declared in <root>.asFairChannel' type=<root>.Flow<*> origin=null
|
||||
action: FUN_EXPR type=kotlin.coroutines.SuspendFunction1<kotlin.Any?, kotlin.Unit> origin=LAMBDA
|
||||
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> (value:kotlin.Any?) returnType:kotlin.Unit [suspend]
|
||||
VALUE_PARAMETER name:value index:0 type:kotlin.Any?
|
||||
action: FUN_EXPR type=kotlin.coroutines.SuspendFunction1<@[ParameterName(name = 'value')] kotlin.Any?, kotlin.Unit> origin=LAMBDA
|
||||
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> (value:@[ParameterName(name = 'value')] kotlin.Any?) returnType:kotlin.Unit [suspend]
|
||||
VALUE_PARAMETER name:value index:0 type:@[ParameterName(name = 'value')] kotlin.Any?
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='local final fun <anonymous> (value: kotlin.Any?): kotlin.Unit [suspend] declared in <root>.asFairChannel.<anonymous>'
|
||||
RETURN type=kotlin.Nothing from='local final fun <anonymous> (value: @[ParameterName(name = 'value')] kotlin.Any?): kotlin.Unit [suspend] declared in <root>.asFairChannel.<anonymous>'
|
||||
CALL 'public final fun sendFair (element: E of <root>.ChannelCoroutine): kotlin.Unit [suspend] declared in <root>.ChannelCoroutine' type=kotlin.Unit origin=null
|
||||
$this: GET_VAR 'val channel: <root>.ChannelCoroutine<kotlin.Any> [val] declared in <root>.asFairChannel.<anonymous>' type=<root>.ChannelCoroutine<kotlin.Any> origin=null
|
||||
element: BLOCK type=kotlin.Any origin=ELVIS
|
||||
VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:kotlin.Any? [val]
|
||||
GET_VAR 'value: kotlin.Any? declared in <root>.asFairChannel.<anonymous>.<anonymous>' type=kotlin.Any? origin=null
|
||||
WHEN type=kotlin.Any origin=ELVIS
|
||||
element: BLOCK type=@[ParameterName(name = 'value')] kotlin.Any origin=ELVIS
|
||||
VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:@[ParameterName(name = 'value')] kotlin.Any? [val]
|
||||
GET_VAR 'value: @[ParameterName(name = 'value')] kotlin.Any? declared in <root>.asFairChannel.<anonymous>.<anonymous>' type=@[ParameterName(name = 'value')] kotlin.Any? origin=null
|
||||
WHEN type=@[ParameterName(name = 'value')] kotlin.Any origin=ELVIS
|
||||
BRANCH
|
||||
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
|
||||
arg0: GET_VAR 'val tmp_0: kotlin.Any? [val] declared in <root>.asFairChannel.<anonymous>.<anonymous>' type=kotlin.Any? origin=null
|
||||
arg0: GET_VAR 'val tmp_0: @[ParameterName(name = 'value')] kotlin.Any? [val] declared in <root>.asFairChannel.<anonymous>.<anonymous>' type=@[ParameterName(name = 'value')] kotlin.Any? origin=null
|
||||
arg1: CONST Null type=kotlin.Nothing? value=null
|
||||
then: CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in kotlin.Any' type=kotlin.Any origin=null
|
||||
BRANCH
|
||||
if: CONST Boolean type=kotlin.Boolean value=true
|
||||
then: GET_VAR 'val tmp_0: kotlin.Any? [val] declared in <root>.asFairChannel.<anonymous>.<anonymous>' type=kotlin.Any? origin=null
|
||||
then: GET_VAR 'val tmp_0: @[ParameterName(name = 'value')] kotlin.Any? [val] declared in <root>.asFairChannel.<anonymous>.<anonymous>' type=@[ParameterName(name = 'value')] kotlin.Any? origin=null
|
||||
FUN name:asChannel visibility:private modality:FINAL <> ($receiver:<root>.CoroutineScope, flow:<root>.Flow<*>) returnType:<root>.ReceiveChannel<kotlin.Any>
|
||||
$receiver: VALUE_PARAMETER name:<this> type:<root>.CoroutineScope
|
||||
VALUE_PARAMETER name:flow index:0 type:<root>.Flow<*>
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='private final fun asChannel (flow: <root>.Flow<*>): <root>.ReceiveChannel<kotlin.Any> declared in <root>'
|
||||
CALL 'public final fun produce <E> (block: @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<<root>.ProducerScope<E of <root>.produce>, kotlin.Unit>): <root>.ReceiveChannel<E of <root>.produce> declared in <root>' type=<root>.ReceiveChannel<kotlin.Any> origin=null
|
||||
<E>: kotlin.Any
|
||||
CALL 'public final fun produce <E> (block: @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<<root>.ProducerScope<E of <root>.produce>, kotlin.Unit>): <root>.ReceiveChannel<E of <root>.produce> declared in <root>' type=<root>.ReceiveChannel<@[ParameterName(name = 'value')] kotlin.Any> origin=null
|
||||
<E>: @[ParameterName(name = 'value')] kotlin.Any
|
||||
$receiver: GET_VAR '<this>: <root>.CoroutineScope declared in <root>.asChannel' type=<root>.CoroutineScope origin=null
|
||||
block: FUN_EXPR type=kotlin.coroutines.SuspendFunction1<<root>.ProducerScope<kotlin.Any>, kotlin.Unit> origin=LAMBDA
|
||||
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> ($receiver:<root>.ProducerScope<kotlin.Any>) returnType:kotlin.Unit [suspend]
|
||||
$receiver: VALUE_PARAMETER name:<this> type:<root>.ProducerScope<kotlin.Any>
|
||||
block: FUN_EXPR type=kotlin.coroutines.SuspendFunction1<<root>.ProducerScope<@[ParameterName(name = 'value')] kotlin.Any>, kotlin.Unit> origin=LAMBDA
|
||||
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> ($receiver:<root>.ProducerScope<@[ParameterName(name = 'value')] kotlin.Any>) returnType:kotlin.Unit [suspend]
|
||||
$receiver: VALUE_PARAMETER name:<this> type:<root>.ProducerScope<@[ParameterName(name = 'value')] kotlin.Any>
|
||||
BLOCK_BODY
|
||||
CALL 'public final fun collect <T> (action: kotlin.coroutines.SuspendFunction1<T of <root>.collect, kotlin.Unit>): kotlin.Unit [inline,suspend] declared in <root>' type=kotlin.Unit origin=null
|
||||
CALL 'public final fun collect <T> (action: kotlin.coroutines.SuspendFunction1<@[ParameterName(name = 'value')] T of <root>.collect, kotlin.Unit>): kotlin.Unit [inline,suspend] declared in <root>' type=kotlin.Unit origin=null
|
||||
<T>: kotlin.Any?
|
||||
$receiver: GET_VAR 'flow: <root>.Flow<*> declared in <root>.asChannel' type=<root>.Flow<*> origin=null
|
||||
action: FUN_EXPR type=kotlin.coroutines.SuspendFunction1<kotlin.Any?, kotlin.Unit> origin=LAMBDA
|
||||
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> (value:kotlin.Any?) returnType:kotlin.Unit [suspend]
|
||||
VALUE_PARAMETER name:value index:0 type:kotlin.Any?
|
||||
action: FUN_EXPR type=kotlin.coroutines.SuspendFunction1<@[ParameterName(name = 'value')] kotlin.Any?, kotlin.Unit> origin=LAMBDA
|
||||
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> (value:@[ParameterName(name = 'value')] kotlin.Any?) returnType:kotlin.Unit [suspend]
|
||||
VALUE_PARAMETER name:value index:0 type:@[ParameterName(name = 'value')] kotlin.Any?
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='local final fun <anonymous> (value: kotlin.Any?): kotlin.Unit [suspend] declared in <root>.asChannel.<anonymous>'
|
||||
RETURN type=kotlin.Nothing from='local final fun <anonymous> (value: @[ParameterName(name = 'value')] kotlin.Any?): kotlin.Unit [suspend] declared in <root>.asChannel.<anonymous>'
|
||||
CALL 'public abstract fun send (e: E of <root>.SendChannel): kotlin.Unit [suspend] declared in <root>.SendChannel' type=kotlin.Unit origin=null
|
||||
$this: CALL 'public abstract fun <get-channel> (): <root>.SendChannel<E of <root>.ProducerScope> declared in <root>.ProducerScope' type=<root>.SendChannel<kotlin.Any> origin=GET_PROPERTY
|
||||
$this: GET_VAR '<this>: <root>.ProducerScope<kotlin.Any> declared in <root>.asChannel.<anonymous>' type=<root>.ProducerScope<kotlin.Any> origin=null
|
||||
e: BLOCK type=kotlin.Any origin=ELVIS
|
||||
VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:kotlin.Any? [val]
|
||||
GET_VAR 'value: kotlin.Any? declared in <root>.asChannel.<anonymous>.<anonymous>' type=kotlin.Any? origin=null
|
||||
WHEN type=kotlin.Any origin=ELVIS
|
||||
$this: CALL 'public abstract fun <get-channel> (): <root>.SendChannel<E of <root>.ProducerScope> declared in <root>.ProducerScope' type=<root>.SendChannel<@[ParameterName(name = 'value')] kotlin.Any> origin=GET_PROPERTY
|
||||
$this: GET_VAR '<this>: <root>.ProducerScope<@[ParameterName(name = 'value')] kotlin.Any> declared in <root>.asChannel.<anonymous>' type=<root>.ProducerScope<@[ParameterName(name = 'value')] kotlin.Any> origin=null
|
||||
e: BLOCK type=@[ParameterName(name = 'value')] kotlin.Any origin=ELVIS
|
||||
VAR IR_TEMPORARY_VARIABLE name:tmp_1 type:@[ParameterName(name = 'value')] kotlin.Any? [val]
|
||||
GET_VAR 'value: @[ParameterName(name = 'value')] kotlin.Any? declared in <root>.asChannel.<anonymous>.<anonymous>' type=@[ParameterName(name = 'value')] kotlin.Any? origin=null
|
||||
WHEN type=@[ParameterName(name = 'value')] kotlin.Any origin=ELVIS
|
||||
BRANCH
|
||||
if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ
|
||||
arg0: GET_VAR 'val tmp_1: kotlin.Any? [val] declared in <root>.asChannel.<anonymous>.<anonymous>' type=kotlin.Any? origin=null
|
||||
arg0: GET_VAR 'val tmp_1: @[ParameterName(name = 'value')] kotlin.Any? [val] declared in <root>.asChannel.<anonymous>.<anonymous>' type=@[ParameterName(name = 'value')] kotlin.Any? origin=null
|
||||
arg1: CONST Null type=kotlin.Nothing? value=null
|
||||
then: CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in kotlin.Any' type=kotlin.Any origin=null
|
||||
BRANCH
|
||||
if: CONST Boolean type=kotlin.Boolean value=true
|
||||
then: GET_VAR 'val tmp_1: kotlin.Any? [val] declared in <root>.asChannel.<anonymous>.<anonymous>' type=kotlin.Any? origin=null
|
||||
then: GET_VAR 'val tmp_1: @[ParameterName(name = 'value')] kotlin.Any? [val] declared in <root>.asChannel.<anonymous>.<anonymous>' type=@[ParameterName(name = 'value')] kotlin.Any? origin=null
|
||||
CLASS CLASS name:SafeCollector modality:FINAL visibility:public superTypes:[<root>.FlowCollector<T of <root>.SafeCollector>]
|
||||
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.SafeCollector<T of <root>.SafeCollector>
|
||||
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?]
|
||||
@@ -211,10 +211,10 @@ FILE fqName:<root> fileName:/castsInsideCoroutineInference.kt
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun flowScope <R> (block: @[ExtensionFunctionType] kotlin.coroutines.SuspendFunction1<<root>.CoroutineScope, R of <root>.flowScope>): R of <root>.flowScope [suspend] declared in <root>'
|
||||
CALL 'public final fun TODO (): kotlin.Nothing [inline] declared in kotlin.StandardKt' type=kotlin.Nothing origin=null
|
||||
FUN name:collect visibility:public modality:FINAL <T> ($receiver:<root>.Flow<T of <root>.collect>, action:kotlin.coroutines.SuspendFunction1<T of <root>.collect, kotlin.Unit>) returnType:kotlin.Unit [inline,suspend]
|
||||
FUN name:collect visibility:public modality:FINAL <T> ($receiver:<root>.Flow<T of <root>.collect>, action:kotlin.coroutines.SuspendFunction1<@[ParameterName(name = 'value')] T of <root>.collect, kotlin.Unit>) returnType:kotlin.Unit [inline,suspend]
|
||||
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Any?]
|
||||
$receiver: VALUE_PARAMETER name:<this> type:<root>.Flow<T of <root>.collect>
|
||||
VALUE_PARAMETER name:action index:0 type:kotlin.coroutines.SuspendFunction1<T of <root>.collect, kotlin.Unit> [crossinline]
|
||||
VALUE_PARAMETER name:action index:0 type:kotlin.coroutines.SuspendFunction1<@[ParameterName(name = 'value')] T of <root>.collect, kotlin.Unit> [crossinline]
|
||||
BLOCK_BODY
|
||||
CLASS CLASS name:ChannelCoroutine modality:OPEN visibility:public superTypes:[kotlin.Any]
|
||||
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.ChannelCoroutine<E of <root>.ChannelCoroutine>
|
||||
|
||||
+10
-10
@@ -10,7 +10,7 @@ fun <R : Any?> scopedFlow(@BuilderInference block: @ExtensionFunctionType Suspen
|
||||
)
|
||||
}
|
||||
|
||||
fun <T : Any?> Flow<T>.onCompletion(action: @ExtensionFunctionType SuspendFunction2<FlowCollector<T>, Throwable?, Unit>): Flow<T> {
|
||||
fun <T : Any?> Flow<T>.onCompletion(action: @ExtensionFunctionType SuspendFunction2<FlowCollector<T>, @ParameterName(name = "cause") Throwable?, Unit>): Flow<T> {
|
||||
return unsafeFlow<T>(block = local suspend fun FlowCollector<T>.<anonymous>() {
|
||||
val safeCollector: SafeCollector<T> = SafeCollector<T>(collector = <this>)
|
||||
safeCollector.invokeSafely<T>(action = action)
|
||||
@@ -18,7 +18,7 @@ fun <T : Any?> Flow<T>.onCompletion(action: @ExtensionFunctionType SuspendFuncti
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun <T : Any?> FlowCollector<T>.invokeSafely(action: @ExtensionFunctionType SuspendFunction2<FlowCollector<T>, Throwable?, Unit>) {
|
||||
suspend fun <T : Any?> FlowCollector<T>.invokeSafely(action: @ExtensionFunctionType SuspendFunction2<FlowCollector<T>, @ParameterName(name = "cause") Throwable?, Unit>) {
|
||||
}
|
||||
|
||||
@OptIn(markerClass = [ExperimentalTypeInference::class])
|
||||
@@ -27,8 +27,8 @@ inline fun <T : Any?> unsafeFlow(@BuilderInference crossinline block: @Extension
|
||||
}
|
||||
|
||||
@Deprecated(message = "binary compatibility with a version w/o FlowCollector receiver", level = DeprecationLevel.HIDDEN)
|
||||
fun <T : Any?> Flow<T>.onCompletion(action: SuspendFunction1<Throwable?, Unit>): Flow<T> {
|
||||
return <this>.onCompletion<T>(action = local suspend fun FlowCollector<T>.<anonymous>(it: Throwable?) {
|
||||
fun <T : Any?> Flow<T>.onCompletion(action: SuspendFunction1<@ParameterName(name = "cause") Throwable?, Unit>): Flow<T> {
|
||||
return <this>.onCompletion<T>(action = local suspend fun FlowCollector<T>.<anonymous>(it: @ParameterName(name = "cause") Throwable?) {
|
||||
action.invoke(p1 = it)
|
||||
}
|
||||
)
|
||||
@@ -37,9 +37,9 @@ fun <T : Any?> Flow<T>.onCompletion(action: SuspendFunction1<Throwable?, Unit>):
|
||||
private fun CoroutineScope.asFairChannel(flow: Flow<*>): ReceiveChannel<Any> {
|
||||
return <this>.produce<Any>(block = local suspend fun ProducerScope<Any>.<anonymous>() {
|
||||
val channel: ChannelCoroutine<Any> = <this>.<get-channel>() as ChannelCoroutine<Any>
|
||||
flow.collect<Any?>(action = local suspend fun <anonymous>(value: Any?) {
|
||||
flow.collect<Any?>(action = local suspend fun <anonymous>(value: @ParameterName(name = "value") Any?) {
|
||||
return channel.sendFair(element = { // BLOCK
|
||||
val <elvis>: Any? = value
|
||||
val <elvis>: @ParameterName(name = "value") Any? = value
|
||||
when {
|
||||
EQEQ(arg0 = <elvis>, arg1 = null) -> Any()
|
||||
else -> <elvis>
|
||||
@@ -52,10 +52,10 @@ private fun CoroutineScope.asFairChannel(flow: Flow<*>): ReceiveChannel<Any> {
|
||||
}
|
||||
|
||||
private fun CoroutineScope.asChannel(flow: Flow<*>): ReceiveChannel<Any> {
|
||||
return <this>.produce<Any>(block = local suspend fun ProducerScope<Any>.<anonymous>() {
|
||||
flow.collect<Any?>(action = local suspend fun <anonymous>(value: Any?) {
|
||||
return <this>.produce<@ParameterName(name = "value") Any>(block = local suspend fun ProducerScope<@ParameterName(name = "value") Any>.<anonymous>() {
|
||||
flow.collect<Any?>(action = local suspend fun <anonymous>(value: @ParameterName(name = "value") Any?) {
|
||||
return <this>.<get-channel>().send(e = { // BLOCK
|
||||
val <elvis>: Any? = value
|
||||
val <elvis>: @ParameterName(name = "value") Any? = value
|
||||
when {
|
||||
EQEQ(arg0 = <elvis>, arg1 = null) -> Any()
|
||||
else -> <elvis>
|
||||
@@ -93,7 +93,7 @@ suspend fun <R : Any?> flowScope(@BuilderInference block: @ExtensionFunctionType
|
||||
return TODO()
|
||||
}
|
||||
|
||||
suspend inline fun <T : Any?> Flow<T>.collect(crossinline action: SuspendFunction1<T, Unit>) {
|
||||
suspend inline fun <T : Any?> Flow<T>.collect(crossinline action: SuspendFunction1<@ParameterName(name = "value") T, Unit>) {
|
||||
}
|
||||
|
||||
open class ChannelCoroutine<E : Any?> {
|
||||
|
||||
@@ -113,6 +113,7 @@ object StandardNames {
|
||||
@JvmField val replaceWith: FqName = fqName("ReplaceWith")
|
||||
@JvmField val extensionFunctionType: FqName = fqName("ExtensionFunctionType")
|
||||
@JvmField val parameterName: FqName = fqName("ParameterName")
|
||||
@JvmField val parameterNameClassId: ClassId = ClassId.topLevel(parameterName)
|
||||
@JvmField val annotation: FqName = fqName("Annotation")
|
||||
@JvmField val target: FqName = annotationName("Target")
|
||||
@JvmField val targetClassId: ClassId = ClassId.topLevel(target)
|
||||
|
||||
@@ -181,6 +181,8 @@ object StandardClassIds {
|
||||
val deprecatedSinceKotlinWarningSince = Name.identifier("warningSince")
|
||||
val deprecatedSinceKotlinErrorSince = Name.identifier("errorSince")
|
||||
val deprecatedSinceKotlinHiddenSince = Name.identifier("hiddenSince")
|
||||
|
||||
val parameterNameName = jvmNameName
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user