New J2K: Add function to lookup symbols by fqName

This commit is contained in:
Simon Ogorodnik
2018-11-13 18:08:13 +03:00
committed by Ilya Kirillov
parent c43bfcb185
commit 77819be8f3
2 changed files with 52 additions and 16 deletions
@@ -6,15 +6,22 @@
package org.jetbrains.kotlin.j2k package org.jetbrains.kotlin.j2k
import com.intellij.psi.* import com.intellij.psi.*
import org.jetbrains.kotlin.j2k.tree.* import org.jetbrains.kotlin.j2k.conversions.resolveFqName
import org.jetbrains.kotlin.j2k.tree.JKClass
import org.jetbrains.kotlin.j2k.tree.JKDeclaration
import org.jetbrains.kotlin.j2k.tree.JKField
import org.jetbrains.kotlin.j2k.tree.JKMethod
import org.jetbrains.kotlin.j2k.tree.impl.* import org.jetbrains.kotlin.j2k.tree.impl.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtNamedFunction import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class JKSymbolProvider { class JKSymbolProvider {
val symbolsByPsi = mutableMapOf<PsiElement, JKSymbol>() val symbolsByPsi = mutableMapOf<PsiElement, JKSymbol>()
val symbolsByJK = mutableMapOf<JKDeclaration, JKSymbol>() val symbolsByJK = mutableMapOf<JKDeclaration, JKSymbol>()
private val elementVisitor = ElementVisitor() private val elementVisitor = ElementVisitor()
fun preBuildTree(files: List<PsiJavaFile>) { fun preBuildTree(files: List<PsiJavaFile>) {
@@ -34,10 +41,10 @@ class JKSymbolProvider {
} }
} }
inline fun <reified T : JKSymbol> provideSymbol(reference: PsiReference): T { internal inline fun <reified T : JKSymbol> provideSymbol(reference: PsiReference): T {
val target = reference.resolve() val target = reference.resolve()
if (target != null) return provideDirectSymbol(target) as T if (target != null) return provideDirectSymbol(target) as T
return JKUnresolvedField(reference).let { if (it is T) it else JKUnresolvedMethod(reference) as T } return (if (isAssignable<T, JKUnresolvedField>()) JKUnresolvedField(reference) else JKUnresolvedMethod(reference)) as T
} }
fun provideUniverseSymbol(psi: PsiElement, jk: JKDeclaration): JKSymbol = provideUniverseSymbol(psi).also { fun provideUniverseSymbol(psi: PsiElement, jk: JKDeclaration): JKSymbol = provideUniverseSymbol(psi).also {
@@ -76,6 +83,17 @@ 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 {
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('/', '.'))
else -> JKUnresolvedClassSymbol(classId.asSingleFqName().asString().replace('/', '.'))
} as T
}
internal inline fun <reified T : JKSymbol> provideByFqName(fqName: String, context: PsiElement = symbolsByPsi.keys.first()): T =
provideByFqName(ClassId.fromString(fqName), context)
private inner class ElementVisitor : JavaElementVisitor() { private inner class ElementVisitor : JavaElementVisitor() {
override fun visitClass(aClass: PsiClass) { override fun visitClass(aClass: PsiClass) {
provideUniverseSymbol(aClass) provideUniverseSymbol(aClass)
@@ -94,4 +112,6 @@ class JKSymbolProvider {
file.acceptChildren(this) file.acceptChildren(this)
} }
} }
internal inline fun <reified A, reified B> isAssignable(): Boolean = A::class.java.isAssignableFrom(B::class.java)
} }
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.psi.KtNamedFunction
interface JKSymbol { interface JKSymbol {
val target: Any val target: Any
val declaredIn: JKSymbol? val declaredIn: JKSymbol?
val fqName: String?
} }
interface JKNamedSymbol : JKSymbol { interface JKNamedSymbol : JKSymbol {
@@ -31,16 +32,14 @@ interface JKUniverseSymbol<T: JKTreeElement> : JKSymbol {
override var target: T override var target: T
} }
interface JKClassSymbol : JKNamedSymbol { interface JKClassSymbol : JKNamedSymbol
val fqName: String?
}
interface JKMethodSymbol : JKNamedSymbol { interface JKMethodSymbol : JKNamedSymbol {
val fqName: String override val fqName: String
} }
interface JKFieldSymbol : JKNamedSymbol { interface JKFieldSymbol : JKNamedSymbol {
val fqName: String override val fqName: String
} }
class JKUniverseClassSymbol : JKClassSymbol, JKUniverseSymbol<JKClass> { class JKUniverseClassSymbol : JKClassSymbol, JKUniverseSymbol<JKClass> {
@@ -121,18 +120,35 @@ class JKMultiverseFieldSymbol(override val target: PsiField) : JKFieldSymbol {
get() = target.name // TODO("Fix this") get() = target.name // TODO("Fix this")
} }
class JKUnresolvedField(override val target: PsiReference) : JKFieldSymbol { class JKUnresolvedField(override val target: String) : JKFieldSymbol {
override val name: String constructor(target: PsiReference) : this(target.canonicalText)
get() = TODO("not implemented")
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.
override val fqName: String = target.canonicalText override val fqName: String = target
override val name: String
get() = target
} }
class JKUnresolvedMethod(override val target: PsiReference) : JKMethodSymbol { class JKUnresolvedMethod(override val target: String) : JKMethodSymbol {
override val name: String constructor(target: PsiReference) : this(target.canonicalText)
get() = TODO("not implemented")
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.
override val fqName: String = target.canonicalText override val fqName: String = target
override val name: String
get() = target
}
class JKUnresolvedClassSymbol(override val target: String) : JKClassSymbol {
override val declaredIn: JKSymbol
get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates.
override val fqName: String?
get() = target
override val name: String
get() = target.substringAfterLast('.')
} }