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