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!!), JKNameIdentifierImpl(name!!),
classKind classKind
).also { ).also {
it.declarationList.apply { it.declarationList = psi.children.mapNotNull {
declarations = psi.children.mapNotNull { ElementVisitor(this@DeclarationMapper).apply { it.accept(this) }.resultElement as? JKUniverseDeclaration
ElementVisitor(this@DeclarationMapper).apply { it.accept(this) }.resultElement as? JKUniverseDeclaration
}
} }
bindSymbol(this, it) bindSymbol(this, it)
@@ -45,10 +45,10 @@ class NewCodeBuilder {
printer.print(classKindString(universeClass.classKind)) printer.print(classKindString(universeClass.classKind))
builder.append(" ") builder.append(" ")
printer.print(universeClass.name.value) printer.print(universeClass.name.value)
if (universeClass.declarationList.declarations.isNotEmpty()) { if (universeClass.declarationList.isNotEmpty()) {
printer.println("{") printer.println("{")
printer.pushIndent() printer.pushIndent()
universeClass.declarationList.declarations.forEach { it.accept(this, data) } universeClass.declarationList.forEach { it.accept(this, data) }
printer.popIndent() printer.popIndent()
printer.println("}") printer.println("}")
} }
@@ -32,7 +32,7 @@ class JavaMethodToKotlinFunctionConversion : TransformerBasedConversion() {
override fun visitUniverseClass(universeClass: JKUniverseClass) { override fun visitUniverseClass(universeClass: JKUniverseClass) {
somethingChanged = true somethingChanged = true
universeClass.declarationList.declarations = universeClass.declarationList.declarations.map { universeClass.declarationList = universeClass.declarationList.map {
if (it is JKJavaMethod) JKKtFunctionImpl( if (it is JKJavaMethod) JKKtFunctionImpl(
JKJavaPrimitiveTypeImpl.BOOLEAN, JKJavaPrimitiveTypeImpl.BOOLEAN,
it.name, it.name,
@@ -6,26 +6,55 @@
package org.jetbrains.kotlin.j2k.conversions package org.jetbrains.kotlin.j2k.conversions
import org.jetbrains.kotlin.j2k.tree.JKTreeElement 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() { abstract class MatchBasedConversion : BaseConversion() {
fun applyRecursive(element: JKTreeElement, func: (JKTreeElement) -> JKTreeElement): JKTreeElement { fun applyRecursive(element: JKTreeElement, func: (JKTreeElement) -> JKTreeElement): JKTreeElement {
if (element is JKMutableBranchElement) { if (element is JKBranchElementBase) {
val iter = element.children.listIterator() val iter = element.children.listIterator()
while (iter.hasNext()) { while (iter.hasNext()) {
val child = iter.next() val child = iter.next()
val newChild = func(child)
if (child !== newChild) { if (child is List<*>) {
onElementChanged(newChild, child) applyRecursiveToList(element, child as List<JKTreeElement>, iter, func)
child.parent = null } else if (child is JKTreeElement) {
newChild.parent = element val newChild = func(child)
iter.set(newChild) if (child !== newChild) {
child.detach(element)
iter.set(newChild)
newChild.attach(element)
onElementChanged(newChild, child)
}
} else {
error("unsupported child type: ${child::class}")
} }
} }
} }
return element 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) 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) { override operator fun setValue(thisRef: JKBranchElementBase, property: KProperty<*>, value: T) {
(thisRef.children[this.value] as T).detach() (thisRef.children[this.value] as T).detach(thisRef)
value.attach(thisRef)
thisRef.children[this.value] = value thisRef.children[this.value] = value
value.attach(thisRef)
} }
} }
class JKListChild<T : JKElement>(val value: Int) : ReadWriteProperty<JKBranchElementBase, List<T>> { class JKListChild<T : JKElement>(val value: Int) : ReadWriteProperty<JKBranchElementBase, List<T>> {
override operator fun getValue(thisRef: JKBranchElementBase, property: KProperty<*>): 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>) { override operator fun setValue(thisRef: JKBranchElementBase, property: KProperty<*>, value: List<T>) {
(thisRef.children[this.value] as List<T>).forEach { it.detach() } (thisRef.children[this.value] as List<T>).forEach { it.detach(thisRef) }
value.forEach { it.attach(thisRef) }
thisRef.children[this.value] = value thisRef.children[this.value] = value
value.forEach { it.attach(thisRef) }
} }
} }
abstract class JKElementBase : JKTreeElement { abstract class JKElementBase : JKTreeElement {
override var parent: JKElement? = null override var parent: JKElement? = null
final override fun detach() { final override fun detach(from: JKElement) {
val prevParent = parent val prevParent = parent
assert(prevParent != null) assert(prevParent != null)
parent = null parent = null
@@ -80,16 +80,18 @@ abstract class JKBranchElementBase : JKElementBase(), JKBranchElement {
protected var childNum = 0 protected var childNum = 0
protected fun <T : JKTreeElement, U : T> child(v: U): ReadWriteProperty<JKBranchElementBase, T> { protected fun <T : JKTreeElement, U : T> child(v: U): ReadWriteProperty<JKBranchElementBase, T> {
children.add(childNum, v) children.add(childNum, v)
v.attach(this)
return JKChild(childNum++) return JKChild(childNum++)
} }
protected inline fun <reified T : JKTreeElement> child(): ReadWriteProperty<JKBranchElementBase, List<T>> { protected inline fun <reified T : JKTreeElement> children(): ReadWriteProperty<JKBranchElementBase, List<T>> {
children[childNum] = listOf<T>() children.add(childNum, listOf<T>())
return JKListChild(childNum++) return JKListChild(childNum++)
} }
protected inline fun <reified T : JKTreeElement> child(v: List<T>): ReadWriteProperty<JKBranchElementBase, List<T>> { protected inline fun <reified T : JKTreeElement> children(v: List<T>): ReadWriteProperty<JKBranchElementBase, List<T>> {
children[childNum] = v children.add(childNum, v)
v.forEach { it.attach(this) }
return JKListChild(childNum++) return JKListChild(childNum++)
} }
@@ -113,7 +115,7 @@ class JKClassImpl(modifierList: JKModifierList, name: JKNameIdentifier, override
override var modifierList by child(modifierList) override var modifierList by child(modifierList)
override val valid: Boolean = true 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) 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 JKNameIdentifierImpl(override val value: String) : JKNameIdentifier, JKElementBase() {}
class JKModifierListImpl(modifiers: List<JKModifier> = emptyList()) : JKModifierList, JKBranchElementBase() { 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) 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() { 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) 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() { 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) override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitExpressionList(this, data)
} }
@@ -23,7 +23,7 @@ interface JKQualifier
interface JKElement { interface JKElement {
val parent: JKElement? val parent: JKElement?
fun detach() fun detach(from: JKElement)
fun attach(to: JKElement) fun attach(to: JKElement)
} }