[FIR] Extract java class mapping to platform specific component

This commit is contained in:
Dmitriy Novozhilov
2020-08-28 13:46:05 +03:00
parent a0b931792e
commit 375140ebcc
4 changed files with 54 additions and 9 deletions
@@ -8,9 +8,11 @@ package org.jetbrains.kotlin.fir.java
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.registerJvmEffectiveVisibilityResolver
import org.jetbrains.kotlin.fir.resolve.calls.jvm.registerJvmCallConflictResolverFactory
import org.jetbrains.kotlin.fir.resolve.registerJavaClassMapper
fun FirSession.registerJavaSpecificComponents() {
registerJavaVisibilityChecker()
registerJvmCallConflictResolverFactory()
registerJvmEffectiveVisibilityResolver()
registerJavaClassMapper()
}
@@ -0,0 +1,22 @@
/*
* 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.fir.resolve
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
class FirJavaClassMapper(private val session: FirSession) : FirPlatformClassMapper() {
override fun getCorrespondingPlatformClass(declaration: FirClassLikeDeclaration<*>): FirRegularClass? {
val javaClassId = JavaToKotlinClassMap.mapKotlinToJava(declaration.symbol.classId.asSingleFqName().toUnsafe())
return javaClassId?.let { session.firSymbolProvider.getClassLikeSymbolByFqName(it)?.fir } as? FirRegularClass
}
}
fun FirSession.registerJavaClassMapper() {
register(FirPlatformClassMapper::class, FirJavaClassMapper(this))
}
@@ -0,0 +1,23 @@
/*
* 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.fir.resolve
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.FirSessionComponent
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
abstract class FirPlatformClassMapper : FirSessionComponent {
object Default : FirPlatformClassMapper() {
override fun getCorrespondingPlatformClass(declaration: FirClassLikeDeclaration<*>): FirRegularClass? {
return null
}
}
abstract fun getCorrespondingPlatformClass(declaration: FirClassLikeDeclaration<*>): FirRegularClass?
}
val FirSession.platformClassMapper: FirPlatformClassMapper by FirSession.sessionComponentAccessor()
@@ -5,16 +5,15 @@
package org.jetbrains.kotlin.fir.resolve
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.resolve.transformers.createSubstitutionForSupertype
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
import org.jetbrains.kotlin.fir.scopes.impl.FirClassSubstitutionScope
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.typeContext
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.name.ClassId
@@ -94,16 +93,15 @@ fun ConeClassLikeType.wrapSubstitutionScopeIfNeed(
return builder.getOrBuild(declaration.symbol, SubstitutionScopeKey(this)) {
val typeParameters = (declaration as? FirTypeParameterRefsOwner)?.typeParameters.orEmpty()
val originalSubstitution = createSubstitution(typeParameters, typeArguments, session)
val javaClassId = JavaToKotlinClassMap.mapKotlinToJava(declaration.symbol.classId.asSingleFqName().toUnsafe())
val javaClass = javaClassId?.let { session.firSymbolProvider.getClassLikeSymbolByFqName(it)?.fir } as? FirRegularClass
if (javaClass != null) {
val platformClass = session.platformClassMapper.getCorrespondingPlatformClass(declaration)
if (platformClass != null) {
// This kind of substitution is necessary when method which is mapped from Java (e.g. Java Map.forEach)
// is called on an external type, like MyMap<String, String>,
// to determine parameter types properly (e.g. String, String instead of K, V)
val javaTypeParameters = javaClass.typeParameters
val javaSubstitution = createSubstitution(javaTypeParameters, typeArguments, session)
val platformTypeParameters = platformClass.typeParameters
val platformSubstitution = createSubstitution(platformTypeParameters, typeArguments, session)
FirClassSubstitutionScope(
session, useSiteMemberScope, builder, originalSubstitution + javaSubstitution,
session, useSiteMemberScope, builder, originalSubstitution + platformSubstitution,
skipPrivateMembers = true, derivedClassId = derivedClassId
)
} else {