[go: nahoru, domu]

blob: 077425921ff3d3307ea0f3fe4375ebcd0acc04bf [file] [log] [blame]
/*
* Copyright 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.compose.compiler.plugins.kotlin
import androidx.compose.compiler.plugins.kotlin.analysis.ComposeWritableSlices
import androidx.compose.compiler.plugins.kotlin.analysis.ComposeWritableSlices.INFERRED_COMPOSABLE_DESCRIPTOR
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
import org.jetbrains.kotlin.extensions.internal.TypeResolutionInterceptorExtension
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtLambdaExpression
import org.jetbrains.kotlin.psi.psiUtil.getAnnotationEntries
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext
/**
* If a lambda is marked as `@Composable`, then the inferred type should become `@Composable`
*/
@Suppress("INVISIBLE_REFERENCE", "EXPERIMENTAL_IS_NOT_ENABLED")
@OptIn(org.jetbrains.kotlin.extensions.internal.InternalNonStableExtensionPoints::class)
open class ComposeTypeResolutionInterceptorExtension : TypeResolutionInterceptorExtension {
override fun interceptFunctionLiteralDescriptor(
expression: KtLambdaExpression,
context: ExpressionTypingContext,
descriptor: AnonymousFunctionDescriptor
): AnonymousFunctionDescriptor {
if (context.expectedType.hasComposableAnnotation()) {
// If the expected type has an @Composable annotation then the literal function
// expression should infer a an @Composable annotation
context.trace.record(INFERRED_COMPOSABLE_DESCRIPTOR, descriptor, true)
}
return descriptor
}
override fun interceptType(
element: KtElement,
context: ExpressionTypingContext,
resultType: KotlinType
): KotlinType {
if (resultType === TypeUtils.NO_EXPECTED_TYPE) return resultType
if (element !is KtLambdaExpression) return resultType
if (
element.getAnnotationEntries().hasComposableAnnotation(context.trace.bindingContext) ||
context.expectedType.hasComposableAnnotation()
) {
context.trace.record(ComposeWritableSlices.INFERRED_COMPOSABLE_LITERAL, element, true)
return resultType.makeComposable(context.scope.ownerDescriptor.module)
}
return resultType
}
}