New J2K: Assignment expression conversion improvements

This commit is contained in:
Dimach
2018-07-18 02:08:21 +03:00
committed by Ilya Kirillov
parent b702e207c0
commit 3a2b2d9e97
5 changed files with 70 additions and 30 deletions
@@ -12,10 +12,12 @@ import org.jetbrains.kotlin.j2k.tree.JKField
import org.jetbrains.kotlin.j2k.tree.JKMethod 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.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtNamedFunction
class JKSymbolProvider { class JKSymbolProvider {
val symbols = mutableMapOf<PsiElement, JKSymbol>() val symbolsByPsi = mutableMapOf<PsiElement, JKSymbol>()
val symbolsByJK = mutableMapOf<JKDeclaration, JKSymbol>()
private val elementVisitor = ElementVisitor() private val elementVisitor = ElementVisitor()
fun preBuildTree(files: List<PsiJavaFile>) { fun preBuildTree(files: List<PsiJavaFile>) {
@@ -23,12 +25,13 @@ class JKSymbolProvider {
} }
fun provideDirectSymbol(psi: PsiElement): JKSymbol { fun provideDirectSymbol(psi: PsiElement): JKSymbol {
return symbols.getOrPut(psi) { return symbolsByPsi.getOrPut(psi) {
when (psi) { when (psi) {
is PsiClass -> JKMultiverseClassSymbol(psi) is PsiClass -> JKMultiverseClassSymbol(psi)
is KtClassOrObject -> JKMultiverseKtClassSymbol(psi) is KtClassOrObject -> JKMultiverseKtClassSymbol(psi)
is PsiMethod -> JKMultiverseMethodSymbol(psi) is PsiMethod -> JKMultiverseMethodSymbol(psi)
is PsiField -> JKMultiverseFieldSymbol(psi) is PsiField -> JKMultiverseFieldSymbol(psi)
is KtNamedFunction -> JKMultiverseFunctionSymbol(psi)
else -> TODO(psi::class.toString()) else -> TODO(psi::class.toString())
} }
} }
@@ -40,22 +43,36 @@ class JKSymbolProvider {
return JKUnresolvedField(reference).let { if (it is T) it else JKUnresolvedMethod(reference) as T } return JKUnresolvedField(reference).let { if (it is T) it else JKUnresolvedMethod(reference) as T }
} }
fun provideUniverseSymbol(psi: PsiElement, jk: JKDeclaration? = null): JKSymbol = symbols.getOrPut(psi) { fun provideUniverseSymbol(psi: PsiElement, jk: JKDeclaration): JKSymbol = provideUniverseSymbol(psi).also {
when (it) {
is JKUniverseClassSymbol -> it.target = jk as JKClass
is JKUniverseFieldSymbol -> it.target = jk as JKField
is JKUniverseMethodSymbol -> it.target = jk as JKMethod
}
symbolsByJK[jk] = it
}
fun provideUniverseSymbol(psi: PsiElement): JKSymbol = symbolsByPsi.getOrPut(psi) {
when (psi) { when (psi) {
is PsiField, is PsiParameter, is PsiLocalVariable -> JKUniverseFieldSymbol() is PsiField, is PsiParameter, is PsiLocalVariable -> JKUniverseFieldSymbol()
is PsiMethod -> JKUniverseMethodSymbol() is PsiMethod -> JKUniverseMethodSymbol()
is PsiClass -> JKUniverseClassSymbol() is PsiClass -> JKUniverseClassSymbol()
else -> TODO() else -> TODO()
} }
}.also {
if (jk != null)
when (it) {
is JKUniverseClassSymbol -> it.target = jk as JKClass
is JKUniverseFieldSymbol -> it.target = jk as JKField
is JKUniverseMethodSymbol -> it.target = jk as JKMethod
}
} }
fun provideUniverseSymbol(jk: JKClass): JKClassSymbol = symbolsByJK.getOrPut(jk) {
JKUniverseClassSymbol().also { it.target = jk }
} as JKClassSymbol
fun provideUniverseSymbol(jk: JKField): JKFieldSymbol = symbolsByJK.getOrPut(jk) {
JKUniverseFieldSymbol().also { it.target = jk }
} as JKFieldSymbol
fun provideUniverseSymbol(jk: JKMethod): JKMethodSymbol = symbolsByJK.getOrPut(jk) {
JKUniverseMethodSymbol().also { it.target = jk }
} as JKMethodSymbol
private inner class ElementVisitor : JavaElementVisitor() { private inner class ElementVisitor : JavaElementVisitor() {
override fun visitClass(aClass: PsiClass) { override fun visitClass(aClass: PsiClass) {
provideUniverseSymbol(aClass) provideUniverseSymbol(aClass)
@@ -6,28 +6,31 @@
package org.jetbrains.kotlin.j2k.conversions package org.jetbrains.kotlin.j2k.conversions
import org.jetbrains.kotlin.j2k.ConversionContext import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.tree.JKExpressionStatement import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.JKJavaAssignmentExpression
import org.jetbrains.kotlin.j2k.tree.JKTreeElement
import org.jetbrains.kotlin.j2k.tree.impl.* import org.jetbrains.kotlin.j2k.tree.impl.*
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
class AssignmentAsExpressionToAlsoConversion(val context: ConversionContext) : RecursiveApplicableConversionBase() { class AssignmentAsExpressionToAlsoConversion(val context: ConversionContext) : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement { override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKJavaAssignmentExpression || element.parent !is JKExpressionStatement) return recurse(element) if (element !is JKJavaAssignmentExpression) return recurse(element)
val alsoSymbol = context.symbolProvider.provideDirectSymbol(
resolveFqName(ClassId.fromString("kotlin/also"), element.getParentOfType<JKClass>() ?: element, context)!!
) as JKMethodSymbol
val alsoElement = resolveFqName(ClassId.fromString("kotlin/also"), element, context) ?: return recurse(element) val alsoExpression = JKKtAlsoCallExpressionImpl(
val alsoSymbol = context.symbolProvider.provideDirectSymbol(alsoElement) as? JKMethodSymbol ?: return recurse(element) JKKtAssignmentStatementImpl(element.field, JKStubExpressionImpl(), element.operator), alsoSymbol
).also {
(it.statement as JKKtAssignmentStatement).expression =
JKKtFieldAccessExpressionImpl(context.symbolProvider.provideUniverseSymbol(it.parameter))
}
element.invalidate() element.invalidate()
return JKQualifiedExpressionImpl( return JKQualifiedExpressionImpl(
element.expression, element.expression,
JKKtQualifierImpl.DOT, JKKtQualifierImpl.DOT,
JKKtCallExpressionImpl(alsoSymbol, JKExpressionListImpl( alsoExpression
// TODO: Lambda expression here
))
) )
} }
} }
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.visitors.JKVisitor import org.jetbrains.kotlin.j2k.tree.visitors.JKVisitor
import org.jetbrains.kotlin.lexer.KtSingleValueToken import org.jetbrains.kotlin.lexer.KtSingleValueToken
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.utils.addToStdlib.cast
class JKKtPropertyImpl( class JKKtPropertyImpl(
modifierList: JKModifierList, modifierList: JKModifierList,
@@ -129,13 +130,11 @@ class JKKtModifierImpl(override val type: JKKtModifier.KtModifierType) : JKKtMod
} }
class JKKtAlsoCallExpressionImpl( class JKKtAlsoCallExpressionImpl(
override val statement: JKStatement, override val statement: JKStatement, override val identifier: JKMethodSymbol, override val parameterName: String = "it"
override val parameterName: String = "it"
) : JKKtAlsoCallExpression, JKBranchElementBase() { ) : JKKtAlsoCallExpression, JKBranchElementBase() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitKtAlsoCallExpression(this, data) override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitKtAlsoCallExpression(this, data)
val parameter
override val identifier get() = arguments.expressions.first().cast<JKLambdaExpression>().parameters.first()
get() = TODO()
override var arguments: JKExpressionList by child( override var arguments: JKExpressionList by child(
JKExpressionListImpl( JKExpressionListImpl(
listOf( listOf(
@@ -151,4 +150,12 @@ class JKKtAlsoCallExpressionImpl(
) )
) )
) )
}
class JKKtAssignmentStatementImpl(
override var field: JKAssignableExpression, expression: JKExpression, override var operator: JKOperator
) : JKKtAssignmentStatement, JKBranchElementBase() {
override var expression by child(expression)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitKtAssignmentStatement(this, data)
} }
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.j2k.tree.JKClass
import org.jetbrains.kotlin.j2k.tree.JKField import org.jetbrains.kotlin.j2k.tree.JKField
import org.jetbrains.kotlin.j2k.tree.JKMethod import org.jetbrains.kotlin.j2k.tree.JKMethod
import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtNamedFunction
interface JKSymbol { interface JKSymbol {
val target: Any val target: Any
@@ -70,11 +71,14 @@ class JKMultiverseMethodSymbol(override val target: PsiMethod) : JKMethodSymbol
} }
class JKUniverseFieldSymbol() : JKFieldSymbol { class JKMultiverseFunctionSymbol(override val target: KtNamedFunction) : JKMethodSymbol {
constructor(target: JKField) : this() { override val declaredIn: JKSymbol
this.target = target get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates.
} override val fqName: String
get() = target.name!!
}
class JKUniverseFieldSymbol : JKFieldSymbol {
override lateinit var target: JKField override lateinit var target: JKField
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.
@@ -64,4 +64,13 @@ interface JKJavaPrimitiveType : JKType {
interface JKJavaArrayType : JKType { interface JKJavaArrayType : JKType {
val type: JKType val type: JKType
} }
inline fun <reified T> JKElement.getParentOfType(): T? {
var p = parent
while (true) {
if (p is T || p == null)
return p as? T
p = p.parent
}
}