diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/fir/KtDeclarationAndFirDeclarationEqualityChecker.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/fir/KtDeclarationAndFirDeclarationEqualityChecker.kt index 482a1e10eb8..1c4e704133f 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/fir/KtDeclarationAndFirDeclarationEqualityChecker.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/fir/KtDeclarationAndFirDeclarationEqualityChecker.kt @@ -16,6 +16,7 @@ import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.FirScopeProvider import org.jetbrains.kotlin.fir.scopes.FirTypeScope +import org.jetbrains.kotlin.fir.symbols.StandardClassIds import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.psi.KtFunction import org.jetbrains.kotlin.psi.KtTypeReference @@ -89,12 +90,27 @@ object KtDeclarationAndFirDeclarationEqualityChecker { else -> error("Invalid type reference $this") } return if (isVararg) { - "kotlin.Array" + rendered.asArrayType() } else { rendered } } + private fun String.asArrayType(): String { + classIdToName[this]?.let { return it } + return "kotlin.Array" + } + + @OptIn(ExperimentalStdlibApi::class) + private val classIdToName: Map = buildList { + StandardClassIds.primitiveArrayTypeByElementType.mapTo(this) { (classId, arrayClassId) -> + classId.asString().replace('/', '.') to arrayClassId.asString().replace('/', '.') + } + StandardClassIds.unsignedArrayTypeByElementType.mapTo(this) { (classId, arrayClassId) -> + classId.asString().replace('/', '.') to arrayClassId.asString().replace('/', '.') + } + }.toMap() + private fun FirTypeProjection.renderTypeAsKotlinType() = when (this) { is FirStarProjection -> "*" is FirTypeProjectionWithVariance -> buildString { diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/KotlinFirReferenceContributor.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/KotlinFirReferenceContributor.kt index 331371fe76e..10645d520c3 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/KotlinFirReferenceContributor.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/KotlinFirReferenceContributor.kt @@ -15,6 +15,7 @@ class KotlinFirReferenceContributor : KotlinReferenceProviderContributor { registerProvider(factory = ::KtFirDestructuringDeclarationReference) registerProvider(factory = ::KtFirArrayAccessReference) registerProvider(factory = ::KtFirConstructorDelegationReference) + registerProvider(factory = ::KtFirCollectionLiteralReference) } } } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/KtFirCollectionLiteralReference.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/KtFirCollectionLiteralReference.kt new file mode 100644 index 00000000000..1fdabf77e94 --- /dev/null +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/KtFirCollectionLiteralReference.kt @@ -0,0 +1,59 @@ +/* + * 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.idea.references + +import org.jetbrains.kotlin.fir.declarations.FirFunction +import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction +import org.jetbrains.kotlin.fir.expressions.FirArrayOfCall +import org.jetbrains.kotlin.fir.resolve.firSymbolProvider +import org.jetbrains.kotlin.fir.symbols.CallableId +import org.jetbrains.kotlin.fir.symbols.StandardClassIds +import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol +import org.jetbrains.kotlin.fir.types.ConeClassLikeType +import org.jetbrains.kotlin.fir.types.coneType +import org.jetbrains.kotlin.fir.types.coneTypeSafe +import org.jetbrains.kotlin.idea.fir.low.level.api.api.getOrBuildFirSafe +import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession +import org.jetbrains.kotlin.idea.frontend.api.fir.KtFirAnalysisSession +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtSymbol +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.KtCollectionLiteralExpression + +class KtFirCollectionLiteralReference( + expression: KtCollectionLiteralExpression +) : KtCollectionLiteralReference(expression), KtFirReference { + override fun KtAnalysisSession.resolveToSymbols(): Collection { + check(this is KtFirAnalysisSession) + val fir = element.getOrBuildFirSafe(firResolveState) ?: return emptyList() + val type = fir.typeRef.coneTypeSafe() ?: return listOfNotNull(arrayOfSymbol(arrayOf)) + val call = arrayTypeToArrayOfCall[type.lookupTag.classId] ?: arrayOf + return listOfNotNull(arrayOfSymbol(call)) + } + + private fun KtFirAnalysisSession.arrayOfSymbol(identifier: Name): KtSymbol? { + val fir = firResolveState.rootModuleSession.firSymbolProvider.getTopLevelCallableSymbols(kotlinPackage, identifier).firstOrNull { + /* choose (for byte array) + * public fun byteArrayOf(vararg elements: kotlin.Byte): kotlin.ByteArray + */ + (it as? FirFunctionSymbol<*>)?.fir?.valueParameters?.singleOrNull()?.isVararg == true + }?.fir as? FirSimpleFunction ?: return null + return firSymbolBuilder.buildFunctionSymbol(fir) + } + + companion object { + private val kotlinPackage = FqName("kotlin") + private val arrayOf = Name.identifier("arrayOf") + private val arrayTypeToArrayOfCall = run { + StandardClassIds.primitiveArrayTypeByElementType.values + StandardClassIds.unsignedArrayTypeByElementType.values + }.associateWith { it.correspondingArrayOfCallFqName() } + + private fun ClassId.correspondingArrayOfCallFqName(): Name = + Name.identifier("${shortClassName.identifier.decapitalize()}Of") + + } +} \ No newline at end of file diff --git a/idea/testData/resolve/references/CollectionLiteralLeft.kt b/idea/testData/resolve/references/CollectionLiteralLeft.kt index 8ce91bd0a38..6f14f4872a3 100644 --- a/idea/testData/resolve/references/CollectionLiteralLeft.kt +++ b/idea/testData/resolve/references/CollectionLiteralLeft.kt @@ -1,5 +1,3 @@ -// IGNORE_FIR - val abc = [1, 2, 3] // REF: (kotlin).arrayOf(vararg T) \ No newline at end of file diff --git a/idea/testData/resolve/references/CollectionLiteralRight.kt b/idea/testData/resolve/references/CollectionLiteralRight.kt index d78af345064..ca056e4de81 100644 --- a/idea/testData/resolve/references/CollectionLiteralRight.kt +++ b/idea/testData/resolve/references/CollectionLiteralRight.kt @@ -1,5 +1,3 @@ -// IGNORE_FIR - val abc: IntArray = [1, 2, 3] // REF: (kotlin).intArrayOf(vararg kotlin.Int) \ No newline at end of file