New J2K: Add from argument to detach

Support detach/attach/multilist in applyRecursive

Clarify attach/detach/onElementChanged order
This commit is contained in:
Simon Ogorodnik
2018-05-18 18:50:40 +03:00
committed by Ilya Kirillov
parent 9b205c2825
commit 985e94fbf3
6 changed files with 59 additions and 30 deletions
@@ -218,10 +218,8 @@ class JavaToJKTreeBuilder {
JKNameIdentifierImpl(name!!),
classKind
).also {
it.declarationList.apply {
declarations = psi.children.mapNotNull {
ElementVisitor(this@DeclarationMapper).apply { it.accept(this) }.resultElement as? JKUniverseDeclaration
}
it.declarationList = psi.children.mapNotNull {
ElementVisitor(this@DeclarationMapper).apply { it.accept(this) }.resultElement as? JKUniverseDeclaration
}
bindSymbol(this, it)
@@ -45,10 +45,10 @@ class NewCodeBuilder {
printer.print(classKindString(universeClass.classKind))
builder.append(" ")
printer.print(universeClass.name.value)
if (universeClass.declarationList.declarations.isNotEmpty()) {
if (universeClass.declarationList.isNotEmpty()) {
printer.println("{")
printer.pushIndent()
universeClass.declarationList.declarations.forEach { it.accept(this, data) }
universeClass.declarationList.forEach { it.accept(this, data) }
printer.popIndent()
printer.println("}")
}
@@ -32,7 +32,7 @@ class JavaMethodToKotlinFunctionConversion : TransformerBasedConversion() {
override fun visitUniverseClass(universeClass: JKUniverseClass) {
somethingChanged = true
universeClass.declarationList.declarations = universeClass.declarationList.declarations.map {
universeClass.declarationList = universeClass.declarationList.map {
if (it is JKJavaMethod) JKKtFunctionImpl(
JKJavaPrimitiveTypeImpl.BOOLEAN,
it.name,
@@ -6,26 +6,55 @@
package org.jetbrains.kotlin.j2k.conversions
import org.jetbrains.kotlin.j2k.tree.JKTreeElement
import org.jetbrains.kotlin.j2k.tree.impl.JKMutableBranchElement
import org.jetbrains.kotlin.j2k.tree.impl.JKBranchElementBase
abstract class MatchBasedConversion : BaseConversion() {
fun applyRecursive(element: JKTreeElement, func: (JKTreeElement) -> JKTreeElement): JKTreeElement {
if (element is JKMutableBranchElement) {
if (element is JKBranchElementBase) {
val iter = element.children.listIterator()
while (iter.hasNext()) {
val child = iter.next()
val newChild = func(child)
if (child !== newChild) {
onElementChanged(newChild, child)
child.parent = null
newChild.parent = element
iter.set(newChild)
if (child is List<*>) {
applyRecursiveToList(element, child as List<JKTreeElement>, iter, func)
} else if (child is JKTreeElement) {
val newChild = func(child)
if (child !== newChild) {
child.detach(element)
iter.set(newChild)
newChild.attach(element)
onElementChanged(newChild, child)
}
} else {
error("unsupported child type: ${child::class}")
}
}
}
return element
}
private inline fun applyRecursiveToList(
element: JKTreeElement,
child: List<JKTreeElement>,
iter: MutableListIterator<Any>,
func: (JKTreeElement) -> JKTreeElement
) {
val newChild = child.map {
func(it)
}
child.forEach { it.detach(element) }
iter.set(child)
newChild.forEach { it.attach(element) }
newChild.zip(child).forEach { (old, new) ->
if (old !== new) {
onElementChanged(new, old)
}
}
}
abstract fun onElementChanged(new: JKTreeElement, old: JKTreeElement)
}
@@ -29,28 +29,28 @@ class JKChild<T : JKElement>(val value: Int) : ReadWriteProperty<JKBranchElement
}
override operator fun setValue(thisRef: JKBranchElementBase, property: KProperty<*>, value: T) {
(thisRef.children[this.value] as T).detach()
value.attach(thisRef)
(thisRef.children[this.value] as T).detach(thisRef)
thisRef.children[this.value] = value
value.attach(thisRef)
}
}
class JKListChild<T : JKElement>(val value: Int) : ReadWriteProperty<JKBranchElementBase, List<T>> {
override operator fun getValue(thisRef: JKBranchElementBase, property: KProperty<*>): List<T> {
return thisRef.children.toList() as List<T>
return thisRef.children[value] as List<T>
}
override operator fun setValue(thisRef: JKBranchElementBase, property: KProperty<*>, value: List<T>) {
(thisRef.children[this.value] as List<T>).forEach { it.detach() }
value.forEach { it.attach(thisRef) }
(thisRef.children[this.value] as List<T>).forEach { it.detach(thisRef) }
thisRef.children[this.value] = value
value.forEach { it.attach(thisRef) }
}
}
abstract class JKElementBase : JKTreeElement {
override var parent: JKElement? = null
final override fun detach() {
final override fun detach(from: JKElement) {
val prevParent = parent
assert(prevParent != null)
parent = null
@@ -80,16 +80,18 @@ abstract class JKBranchElementBase : JKElementBase(), JKBranchElement {
protected var childNum = 0
protected fun <T : JKTreeElement, U : T> child(v: U): ReadWriteProperty<JKBranchElementBase, T> {
children.add(childNum, v)
v.attach(this)
return JKChild(childNum++)
}
protected inline fun <reified T : JKTreeElement> child(): ReadWriteProperty<JKBranchElementBase, List<T>> {
children[childNum] = listOf<T>()
protected inline fun <reified T : JKTreeElement> children(): ReadWriteProperty<JKBranchElementBase, List<T>> {
children.add(childNum, listOf<T>())
return JKListChild(childNum++)
}
protected inline fun <reified T : JKTreeElement> child(v: List<T>): ReadWriteProperty<JKBranchElementBase, List<T>> {
children[childNum] = v
protected inline fun <reified T : JKTreeElement> children(v: List<T>): ReadWriteProperty<JKBranchElementBase, List<T>> {
children.add(childNum, v)
v.forEach { it.attach(this) }
return JKListChild(childNum++)
}
@@ -113,7 +115,7 @@ class JKClassImpl(modifierList: JKModifierList, name: JKNameIdentifier, override
override var modifierList by child(modifierList)
override val valid: Boolean = true
override var declarationList by child<JKUniverseDeclaration>()
override var declarationList by children<JKUniverseDeclaration>()
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitUniverseClass(this, data)
}
@@ -122,7 +124,7 @@ class JKClassImpl(modifierList: JKModifierList, name: JKNameIdentifier, override
class JKNameIdentifierImpl(override val value: String) : JKNameIdentifier, JKElementBase() {}
class JKModifierListImpl(modifiers: List<JKModifier> = emptyList()) : JKModifierList, JKBranchElementBase() {
override var modifiers: List<JKModifier> by child(modifiers)
override var modifiers: List<JKModifier> by children(modifiers)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitModifierList(this, data)
}
@@ -132,7 +134,7 @@ class JKValueArgumentImpl(type: JKType, override val name: String) : JKValueArgu
}
class JKBlockImpl(statements: List<JKStatement> = emptyList()) : JKBlock, JKBranchElementBase() {
override var statements by child(statements)
override var statements by children(statements)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitBlock(this, data)
}
@@ -155,7 +157,7 @@ class JKPostfixExpressionImpl(expression: JKExpression, override var operator: J
}
class JKExpressionListImpl(expressions: List<JKExpression> = emptyList()) : JKExpressionList, JKBranchElementBase() {
override var expressions by child(expressions)
override var expressions by children(expressions)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitExpressionList(this, data)
}
@@ -23,7 +23,7 @@ interface JKQualifier
interface JKElement {
val parent: JKElement?
fun detach()
fun detach(from: JKElement)
fun attach(to: JKElement)
}