org.jetbrains.kotlin.resolve.CollectionLiteralResolver.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kotlin-compiler-embeddable Show documentation
Show all versions of kotlin-compiler-embeddable Show documentation
the Kotlin compiler embeddable
/*
* 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.resolve
import com.intellij.psi.PsiElement
import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.builtins.UnsignedTypes
import org.jetbrains.kotlin.config.LanguageFeature.*
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory1
import org.jetbrains.kotlin.diagnostics.Errors.*
import org.jetbrains.kotlin.incremental.KotlinLookupLocation
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtAnnotationEntry
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtCollectionLiteralExpression
import org.jetbrains.kotlin.psi.KtObjectDeclaration
import org.jetbrains.kotlin.resolve.BindingContext.COLLECTION_LITERAL_CALL
import org.jetbrains.kotlin.resolve.CollectionLiteralResolver.ContainerKind.*
import org.jetbrains.kotlin.resolve.calls.CallResolver
import org.jetbrains.kotlin.resolve.calls.util.CallMaker
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext
import org.jetbrains.kotlin.types.expressions.KotlinTypeInfo
import org.jetbrains.kotlin.types.expressions.typeInfoFactory.createTypeInfo
import org.jetbrains.kotlin.types.expressions.typeInfoFactory.noTypeInfo
class CollectionLiteralResolver(
val module: ModuleDescriptor,
val callResolver: CallResolver,
val languageVersionSettings: LanguageVersionSettings
) {
fun resolveCollectionLiteral(
collectionLiteralExpression: KtCollectionLiteralExpression,
context: ExpressionTypingContext
): KotlinTypeInfo {
when (computeKindOfContainer(collectionLiteralExpression)) {
AnnotationOrAnnotationClass -> {}
CompanionOfAnnotation -> {
val factory = when (context.languageVersionSettings.supportsFeature(ProhibitArrayLiteralsInCompanionOfAnnotation)) {
true -> UNSUPPORTED
false -> UNSUPPORTED_WARNING
}
reportUnsupportedLiteral(context, factory, collectionLiteralExpression)
}
Other -> reportUnsupportedLiteral(context, UNSUPPORTED, collectionLiteralExpression)
}
return resolveCollectionLiteralSpecialMethod(collectionLiteralExpression, context)
}
private fun reportUnsupportedLiteral(
context: ExpressionTypingContext,
diagnosticFactory: DiagnosticFactory1,
collectionLiteralExpression: KtCollectionLiteralExpression
) {
context.trace.report(diagnosticFactory.on(collectionLiteralExpression, "Collection literals outside of annotations"))
}
private fun resolveCollectionLiteralSpecialMethod(
expression: KtCollectionLiteralExpression,
context: ExpressionTypingContext
): KotlinTypeInfo {
val call = CallMaker.makeCallForCollectionLiteral(expression)
val callName = getArrayFunctionCallName(context.expectedType)
val functionDescriptors = getFunctionDescriptorForCollectionLiteral(expression, callName)
if (functionDescriptors.isEmpty()) {
context.trace.report(
MISSING_STDLIB.on(
expression, "Collection literal call '$callName()' is unresolved"
)
)
return noTypeInfo(context)
}
val resolutionResults = callResolver.resolveCollectionLiteralCallWithGivenDescriptor(context, expression, call, functionDescriptors)
if (!resolutionResults.isSingleResult) {
return noTypeInfo(context)
}
context.trace.record(COLLECTION_LITERAL_CALL, expression, resolutionResults.resultingCall)
return createTypeInfo(resolutionResults.resultingDescriptor.returnType, context)
}
private fun getFunctionDescriptorForCollectionLiteral(
expression: KtCollectionLiteralExpression,
callName: Name
): Collection {
val memberScopeOfKotlinPackage = module.getPackage(StandardNames.BUILT_INS_PACKAGE_FQ_NAME).memberScope
return memberScopeOfKotlinPackage.getContributedFunctions(callName, KotlinLookupLocation(expression))
}
private enum class ContainerKind {
AnnotationOrAnnotationClass,
CompanionOfAnnotation,
Other
}
private fun computeKindOfContainer(expression: KtCollectionLiteralExpression): ContainerKind {
val parent = PsiTreeUtil.getParentOfType(expression, KtAnnotationEntry::class.java, KtClass::class.java, KtObjectDeclaration::class.java)
if (parent is KtObjectDeclaration) {
val containingAnnotation = PsiTreeUtil.getParentOfType(parent, KtClass::class.java)
if (containingAnnotation != null && containingAnnotation.isAnnotation()) {
return CompanionOfAnnotation
}
}
return if (parent is KtAnnotationEntry || (parent is KtClass && parent.isAnnotation())) {
AnnotationOrAnnotationClass
} else {
Other
}
}
private fun getArrayFunctionCallName(expectedType: KotlinType): Name {
if (TypeUtils.noExpectedType(expectedType) ||
!(KotlinBuiltIns.isPrimitiveArray(expectedType) || KotlinBuiltIns.isUnsignedArrayType(expectedType))
) {
return ArrayFqNames.ARRAY_OF_FUNCTION
}
val descriptor = expectedType.constructor.declarationDescriptor ?: return ArrayFqNames.ARRAY_OF_FUNCTION
return ArrayFqNames.PRIMITIVE_TYPE_TO_ARRAY[KotlinBuiltIns.getPrimitiveArrayType(descriptor)]
?: UnsignedTypes.unsignedArrayTypeToArrayCall[UnsignedTypes.toUnsignedArrayType(descriptor)]
?: ArrayFqNames.ARRAY_OF_FUNCTION
}
}