[FIR] Move JvmMappedScope to fir:jvm module
This commit is contained in:
committed by
Mikhail Glukhikh
parent
16c82030a3
commit
5b8ab76613
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* 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.scopes.jvm
|
||||
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.types.jvm.FirJavaTypeRef
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaClass
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaClassifierType
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaPrimitiveType
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
fun FirFunction<*>.computeJvmDescriptor(): String = buildString {
|
||||
if (this@computeJvmDescriptor is FirSimpleFunction) {
|
||||
append(name.asString())
|
||||
} else {
|
||||
append("<init>")
|
||||
}
|
||||
|
||||
append("(")
|
||||
for (parameter in valueParameters) {
|
||||
appendErasedType(parameter.returnTypeRef)
|
||||
}
|
||||
append(")")
|
||||
|
||||
if (this@computeJvmDescriptor !is FirSimpleFunction || returnTypeRef.isVoid()) {
|
||||
append("V")
|
||||
} else {
|
||||
appendErasedType(returnTypeRef)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: primitive types, arrays, etc.
|
||||
private fun StringBuilder.appendErasedType(typeRef: FirTypeRef) {
|
||||
fun appendClass(klass: JavaClass) {
|
||||
klass.fqName?.let {
|
||||
append("L")
|
||||
append(it.asString().replace(".", "/"))
|
||||
}
|
||||
}
|
||||
|
||||
when (typeRef) {
|
||||
is FirResolvedTypeRef -> appendConeType(typeRef.type)
|
||||
is FirJavaTypeRef -> {
|
||||
when (val javaType = typeRef.type) {
|
||||
is JavaClassifierType -> {
|
||||
when (val classifier = javaType.classifier) {
|
||||
is JavaClass -> appendClass(classifier)
|
||||
is JavaTypeParameter -> {
|
||||
val representative = classifier.upperBounds.firstOrNull { it.classifier is JavaClass }
|
||||
if (representative == null) {
|
||||
append("Ljava/lang/Object")
|
||||
} else {
|
||||
appendClass(representative.classifier as JavaClass)
|
||||
}
|
||||
}
|
||||
else -> return
|
||||
}
|
||||
append(";")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun StringBuilder.appendConeType(coneType: ConeKotlinType) {
|
||||
fun appendClassLikeType(type: ConeClassLikeType) {
|
||||
append("L")
|
||||
val classId = type.lookupTag.classId
|
||||
append(classId.packageFqName.asString().replace(".", "/"))
|
||||
append("/")
|
||||
append(classId.relativeClassName)
|
||||
}
|
||||
|
||||
if (coneType is ConeClassErrorType) return
|
||||
when (coneType) {
|
||||
is ConeClassLikeType -> {
|
||||
appendClassLikeType(coneType)
|
||||
}
|
||||
is ConeTypeParameterType -> {
|
||||
val representative = coneType.lookupTag.typeParameterSymbol.fir.bounds.firstOrNull {
|
||||
(it as? FirResolvedTypeRef)?.type is ConeClassLikeType
|
||||
}
|
||||
if (representative == null) {
|
||||
append("Ljava/lang/Object")
|
||||
} else {
|
||||
appendClassLikeType(representative.coneTypeUnsafe())
|
||||
}
|
||||
append(coneType.lookupTag.name)
|
||||
}
|
||||
}
|
||||
append(";")
|
||||
}
|
||||
|
||||
private val unitClassId = ClassId.topLevel(FqName("kotlin.Unit"))
|
||||
|
||||
private fun FirTypeRef.isVoid(): Boolean {
|
||||
return when (this) {
|
||||
is FirJavaTypeRef -> {
|
||||
val type = type
|
||||
type is JavaPrimitiveType && type.type == null
|
||||
}
|
||||
is FirResolvedTypeRef -> {
|
||||
val type = type
|
||||
type is ConeClassLikeType && type.lookupTag.classId == unitClassId
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.scopes.jvm
|
||||
|
||||
import org.jetbrains.kotlin.builtins.jvm.JvmBuiltInsSettings
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
class JvmMappedScope(
|
||||
private val declaredMemberScope: FirScope,
|
||||
private val javaMappedClassUseSiteScope: FirScope,
|
||||
private val whiteListSignaturesByName: Map<Name, List<String>>
|
||||
) : FirScope() {
|
||||
|
||||
override fun processFunctionsByName(name: Name, processor: (FirFunctionSymbol<*>) -> ProcessorAction): ProcessorAction {
|
||||
val whiteListSignatures = whiteListSignaturesByName[name]
|
||||
?: return declaredMemberScope.processFunctionsByName(name, processor)
|
||||
if (!javaMappedClassUseSiteScope.processFunctionsByName(name) { symbol ->
|
||||
val jvmSignature = symbol.fir.computeJvmDescriptor()
|
||||
if (jvmSignature !in whiteListSignatures) {
|
||||
ProcessorAction.NEXT
|
||||
} else {
|
||||
processor(symbol)
|
||||
}
|
||||
}
|
||||
) return ProcessorAction.STOP
|
||||
|
||||
return declaredMemberScope.processFunctionsByName(name, processor)
|
||||
}
|
||||
|
||||
override fun processPropertiesByName(name: Name, processor: (FirCallableSymbol<*>) -> ProcessorAction): ProcessorAction {
|
||||
return declaredMemberScope.processPropertiesByName(name, processor)
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun prepareSignatures(klass: FirRegularClass): Map<Name, List<String>> {
|
||||
val signaturePrefix = klass.symbol.classId.toString()
|
||||
val filteredSignatures = JvmBuiltInsSettings.WHITE_LIST_METHOD_SIGNATURES.filter { signature ->
|
||||
signature.startsWith(signaturePrefix)
|
||||
}.map { signature ->
|
||||
// +1 to delete dot before function name
|
||||
signature.substring(signaturePrefix.length + 1)
|
||||
}
|
||||
return filteredSignatures.groupBy { Name.identifier(it.substringBefore("(")) }
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user