New J2K: Cache resolving by fqNames

This commit is contained in:
Ilya Kirillov
2019-02-03 16:56:54 +03:00
committed by Ilya Kirillov
parent ea6cb716e5
commit c111f1c52f
6 changed files with 56 additions and 64 deletions
@@ -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) {