New J2K: Cache resolving by fqNames
This commit is contained in:
committed by
Ilya Kirillov
parent
ea6cb716e5
commit
c111f1c52f
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
|
||||
class JKSymbolProvider {
|
||||
val symbolsByFqName = mutableMapOf<String, JKSymbol>()
|
||||
val symbolsByPsi = mutableMapOf<PsiElement, JKSymbol>()
|
||||
val symbolsByJK = mutableMapOf<JKDeclaration, JKSymbol>()
|
||||
|
||||
@@ -89,30 +90,50 @@ class JKSymbolProvider {
|
||||
JKUniverseMethodSymbol(this).also { it.target = jk }
|
||||
} as JKMethodSymbol
|
||||
|
||||
internal inline fun <reified T : JKSymbol> provideByFqName(classId: ClassId, context: PsiElement = symbolsByPsi.keys.first()): T {
|
||||
return resolveFqName(classId, context)?.let(::provideDirectSymbol).safeAs<T>() ?: when {
|
||||
isAssignable<T, JKUnresolvedMethod>() -> JKUnresolvedMethod(classId.asSingleFqName().asString().replace('/', '.'))
|
||||
isAssignable<T, JKUnresolvedField>() -> JKUnresolvedField(classId.asSingleFqName().asString().replace('/', '.'), this)
|
||||
else -> JKUnresolvedClassSymbol(classId.asSingleFqName().asString().replace('/', '.'))
|
||||
internal inline fun <reified T : JKSymbol> provideByFqName(
|
||||
classId: ClassId,
|
||||
multiResolve: Boolean = false,
|
||||
context: PsiElement = symbolsByPsi.keys.first()
|
||||
): T {
|
||||
val fqName = classId.asSingleFqName().asString().replace('/', '.')
|
||||
if (fqName in symbolsByFqName) {
|
||||
return symbolsByFqName[fqName] as T
|
||||
}
|
||||
val resolved =
|
||||
if (multiResolve) multiResolveFqName(classId, context).firstOrNull()
|
||||
else resolveFqName(classId, context)
|
||||
val symbol = resolved?.let(::provideDirectSymbol).safeAs<T>()
|
||||
return symbol ?: when {
|
||||
isAssignable<T, JKUnresolvedMethod>() -> JKUnresolvedMethod(fqName)
|
||||
isAssignable<T, JKUnresolvedField>() -> JKUnresolvedField(fqName, this)
|
||||
else -> JKUnresolvedClassSymbol(fqName)
|
||||
} as T
|
||||
}
|
||||
|
||||
internal inline fun <reified T : JKSymbol> provideByFqNameMulti(fqName: String, context: PsiElement = symbolsByPsi.keys.first()): T {
|
||||
return multiResolveFqName(ClassId.fromString(fqName), context).firstOrNull()?.let(::provideDirectSymbol).safeAs<T>() ?: when {
|
||||
isAssignable<T, JKUnresolvedMethod>() -> JKUnresolvedMethod(fqName.replace('/', '.'))
|
||||
isAssignable<T, JKUnresolvedField>() -> JKUnresolvedField(fqName.replace('/', '.'), this)
|
||||
else -> JKUnresolvedClassSymbol(fqName.replace('/', '.'))
|
||||
} as T
|
||||
}
|
||||
@Deprecated("", ReplaceWith("provideByFqName(fqName, true, context)"))
|
||||
internal inline fun <reified T : JKSymbol> provideByFqNameMulti(fqName: String, context: PsiElement = symbolsByPsi.keys.first()): T =
|
||||
provideByFqName(ClassId.fromString(fqName), true, context)
|
||||
|
||||
internal inline fun <reified T : JKSymbol> provideByFqName(fqName: String, context: PsiElement = symbolsByPsi.keys.first()): T =
|
||||
provideByFqName(ClassId.fromString(fqName), context)
|
||||
internal inline fun <reified T : JKSymbol> provideByFqName(
|
||||
fqName: String,
|
||||
multiResolve: Boolean = false,
|
||||
context: PsiElement = symbolsByPsi.keys.first()
|
||||
): T =
|
||||
provideByFqName(ClassId.fromString(fqName), multiResolve, context)
|
||||
|
||||
internal inline fun <reified T : JKSymbol> provideByFqName(fqName: FqName, context: PsiElement = symbolsByPsi.keys.first()): T =
|
||||
provideByFqName(fqName.asString(), context)
|
||||
internal inline fun <reified T : JKSymbol> provideByFqName(
|
||||
fqName: FqName,
|
||||
multiResolve: Boolean = false,
|
||||
context: PsiElement = symbolsByPsi.keys.first()
|
||||
): T =
|
||||
provideByFqName(fqName.asString(), multiResolve, context)
|
||||
|
||||
internal inline fun <reified T : JKSymbol> provideByFqName(fqName: FqNameUnsafe, context: PsiElement = symbolsByPsi.keys.first()): T =
|
||||
provideByFqName(fqName.asString(), context)
|
||||
internal inline fun <reified T : JKSymbol> provideByFqName(
|
||||
fqName: FqNameUnsafe,
|
||||
multiResolve: Boolean = false,
|
||||
context: PsiElement = symbolsByPsi.keys.first()
|
||||
): T =
|
||||
provideByFqName(fqName.asString(), multiResolve, context)
|
||||
|
||||
|
||||
private inner class ElementVisitor : JavaElementVisitor() {
|
||||
|
||||
@@ -23,20 +23,13 @@ class BlockToRunConversion(private val context: ConversionContext) : RecursiveAp
|
||||
val parentDeclaration = element.parentOfType<JKDeclaration>() ?: return recurse(element)
|
||||
val psiContext = parentDeclaration.psi ?: return recurse(element)
|
||||
|
||||
val unitType =
|
||||
context.symbolProvider.provideDirectSymbol(
|
||||
resolveFqName(ClassId.topLevel(KotlinBuiltIns.FQ_NAMES.unit.toSafe()), psiContext)!!
|
||||
)
|
||||
val runSymbol = context.symbolProvider.provideDirectSymbol(
|
||||
multiResolveFqName(ClassId.fromString("kotlin/run"), psiContext).first()
|
||||
)
|
||||
|
||||
element.invalidate()
|
||||
val lambda = JKLambdaExpressionImpl(
|
||||
JKBlockStatementImpl(element.block),
|
||||
emptyList()
|
||||
)
|
||||
val call = JKKtCallExpressionImpl(runSymbol as JKMethodSymbol, JKExpressionListImpl(listOf(lambda)))
|
||||
val call = JKKtCallExpressionImpl(context.symbolProvider.provideByFqName("kotlin.run", true), JKExpressionListImpl(listOf(lambda)))
|
||||
return recurse(JKExpressionStatementImpl(call))
|
||||
}
|
||||
|
||||
|
||||
@@ -22,26 +22,19 @@ import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
import java.math.BigInteger
|
||||
|
||||
fun kotlinTypeByName(name: String, symbolProvider: JKSymbolProvider, nullability: Nullability = Nullability.Nullable): JKClassType {
|
||||
val symbol =
|
||||
symbolProvider.provideDirectSymbol(
|
||||
resolveFqName(ClassId.fromString(name), symbolProvider.symbolsByPsi.keys.first())!!
|
||||
) as JKClassSymbol
|
||||
return JKClassTypeImpl(symbol, emptyList(), nullability)
|
||||
}
|
||||
fun kotlinTypeByName(name: String, symbolProvider: JKSymbolProvider, nullability: Nullability = Nullability.Nullable): JKClassType =
|
||||
JKClassTypeImpl(
|
||||
symbolProvider.provideByFqName(name),
|
||||
emptyList(),
|
||||
nullability
|
||||
)
|
||||
|
||||
private fun JKType.classSymbol(symbolProvider: JKSymbolProvider) =
|
||||
when (this) {
|
||||
is JKClassType -> classReference
|
||||
is JKJavaPrimitiveType -> {
|
||||
val psiClass = resolveFqName(
|
||||
ClassId.fromString(jvmPrimitiveType.primitiveType.typeFqName.asString()),
|
||||
symbolProvider.symbolsByPsi.keys.first()
|
||||
)
|
||||
psiClass?.let { klass ->
|
||||
symbolProvider.provideDirectSymbol(klass) as? JKClassSymbol
|
||||
}
|
||||
}
|
||||
is JKJavaPrimitiveType ->
|
||||
symbolProvider.provideByFqName(jvmPrimitiveType.primitiveType.typeFqName.asString())
|
||||
|
||||
else -> null
|
||||
}
|
||||
|
||||
@@ -285,14 +278,7 @@ fun useExpression(
|
||||
body: JKStatement,
|
||||
symbolProvider: JKSymbolProvider
|
||||
): JKExpression {
|
||||
val useSymbol =
|
||||
symbolProvider
|
||||
.provideDirectSymbol(
|
||||
resolveFqName(
|
||||
ClassId.fromString("kotlin.io.use"),
|
||||
symbolProvider.symbolsByPsi.keys.first()
|
||||
)!!
|
||||
) as JKMethodSymbol
|
||||
val useSymbol = symbolProvider.provideByFqName<JKMethodSymbol>("kotlin.io.use")
|
||||
val lambdaParameter =
|
||||
JKParameterImpl(JKTypeElementImpl(JKNoTypeImpl), variableIdentifier)
|
||||
|
||||
|
||||
@@ -229,9 +229,7 @@ class JKBooleanLiteral(val value: Boolean) : JKLiteralExpression, JKElementBase(
|
||||
fun JKLiteralExpression.LiteralType.toJkType(symbolProvider: JKSymbolProvider): JKType {
|
||||
fun defaultTypeByName(name: String) =
|
||||
JKClassTypeImpl(
|
||||
symbolProvider.provideDirectSymbol(
|
||||
resolveFqName(ClassId.fromString("kotlin.$name"), symbolProvider.symbolsByPsi.keys.first())!!
|
||||
) as JKClassSymbol, emptyList(), Nullability.NotNull
|
||||
symbolProvider.provideByFqName("kotlin.$name"), emptyList(), Nullability.NotNull
|
||||
)
|
||||
|
||||
return when (this) {
|
||||
|
||||
@@ -213,11 +213,7 @@ class JKUnresolvedField(override val target: String, private val symbolProvider:
|
||||
get() {
|
||||
val resolvedType = (target as? PsiReferenceExpressionImpl)?.type
|
||||
if (resolvedType != null) return resolvedType.toJK(symbolProvider)
|
||||
|
||||
val nothingSymbol = (symbolProvider.provideDirectSymbol(
|
||||
resolveFqName(ClassId.fromString("kotlin.Nothing"), symbolProvider.symbolsByPsi.keys.first())!!
|
||||
) as JKClassSymbol)
|
||||
return JKClassTypeImpl(nothingSymbol, emptyList())
|
||||
return JKClassTypeImpl(symbolProvider.provideByFqName("kotlin.Nothing"), emptyList())
|
||||
}
|
||||
override val declaredIn: JKSymbol
|
||||
get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates.
|
||||
|
||||
@@ -67,12 +67,10 @@ fun JKExpression.type(symbolProvider: JKSymbolProvider): JKType? =
|
||||
|
||||
fun ClassId.toKtClassType(
|
||||
symbolProvider: JKSymbolProvider,
|
||||
nullability: Nullability = Nullability.Default,
|
||||
context: PsiElement = symbolProvider.symbolsByPsi.keys.first()
|
||||
): JKType {
|
||||
val typeSymbol = symbolProvider.provideDirectSymbol(resolveFqName(this, context)!!) as JKClassSymbol
|
||||
return JKClassTypeImpl(typeSymbol, emptyList(), nullability)
|
||||
}
|
||||
nullability: Nullability = Nullability.Default
|
||||
): JKType =
|
||||
JKClassTypeImpl(symbolProvider.provideByFqName(this), emptyList(), nullability)
|
||||
|
||||
|
||||
fun PsiType.toJK(symbolProvider: JKSymbolProvider, nullability: Nullability = Nullability.Default): JKType {
|
||||
return when (this) {
|
||||
|
||||
Reference in New Issue
Block a user