From a7e0f18a571bfa669e352cbf70cf509fe906ced7 Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Tue, 9 Oct 2018 12:29:36 +0300 Subject: [PATCH] New J2K: Add primary constructor initializers conversion --- .../jetbrains/kotlin/j2k/ConversionsRunner.kt | 1 + .../jetbrains/kotlin/j2k/NewCodeBuilder.kt | 8 ++- ...itializersInPrimaryFromParamsConversion.kt | 52 +++++++++++++++++++ .../org/jetbrains/kotlin/j2k/tree/impl/jk.kt | 4 +- .../org/jetbrains/kotlin/j2k/tree/jk.kt | 2 +- 5 files changed, 62 insertions(+), 5 deletions(-) create mode 100644 j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/FieldInitializersInPrimaryFromParamsConversion.kt diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/ConversionsRunner.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/ConversionsRunner.kt index 1881c02023d..0dad9a66135 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/ConversionsRunner.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/ConversionsRunner.kt @@ -39,6 +39,7 @@ object ConversionsRunner { +ConstructorConversion(context) +PrimaryConstructorDetectConversion(context) +InsertDefaultPrimaryConstructorConversion(context) + +FieldInitializersInPrimaryFromParamsConversion() +JavaMethodToKotlinFunctionConversion() +LiteralConversion() +InnerClassConversion() diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/NewCodeBuilder.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/NewCodeBuilder.kt index 2c11f1d6956..b3a9b5a1a63 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/NewCodeBuilder.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/NewCodeBuilder.kt @@ -103,7 +103,10 @@ class NewCodeBuilder { ) } - override fun visitMutabilityModifier(mutabilityModifier: JKMutabilityModifier) {} + override fun visitMutabilityModifier(mutabilityModifier: JKMutabilityModifier) { + if (mutabilityModifier.mutability == Mutability.NonMutable) printer.print("val") + else printer.print("var") + } override fun visitKtModifier(ktModifier: JKKtModifier) { printer.printWithNoIndent( @@ -189,7 +192,8 @@ class NewCodeBuilder { override fun visitParameter(parameter: JKParameter) { - printer.printWithNoIndent(parameter.name.value, ": ") + parameter.modifierList.accept(this) + printer.printWithNoIndent(" ", parameter.name.value, ": ") parameter.type.accept(this) if (parameter.initializer !is JKStubExpression) { printer.printWithNoIndent(" = ") diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/FieldInitializersInPrimaryFromParamsConversion.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/FieldInitializersInPrimaryFromParamsConversion.kt new file mode 100644 index 00000000000..cf2384dc8c6 --- /dev/null +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/FieldInitializersInPrimaryFromParamsConversion.kt @@ -0,0 +1,52 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.j2k.conversions + +import org.jetbrains.kotlin.j2k.tree.* +import org.jetbrains.kotlin.j2k.tree.impl.JKJavaFieldImpl +import org.jetbrains.kotlin.j2k.tree.impl.JKNameIdentifierImpl + + +class FieldInitializersInPrimaryFromParamsConversion : TransformerBasedConversion() { + override fun visitTreeElement(treeElement: JKTreeElement) { + treeElement.acceptChildren(this, null) + } + + override fun visitKtPrimaryConstructor(ktPrimaryConstructor: JKKtPrimaryConstructor) { + for (constructorStatement in ktPrimaryConstructor.block.statements) { + val assignmentExpression = + (constructorStatement as? JKExpressionStatement)?.expression as? JKJavaAssignmentExpression ?: continue + //TODO check if operator is `=` + val smartField = assignmentExpression.smartField() ?: continue + val fieldTarget = smartField.identifier.target as? JKJavaFieldImpl ?: continue + val parameter = + (assignmentExpression.expression as? JKFieldAccessExpression)?.identifier?.target as? JKParameter ?: continue + if (ktPrimaryConstructor.parameters.contains(parameter)) { + val containingClass = ktPrimaryConstructor.parentOfType() ?: continue + val fieldDeclaration = containingClass.declarationList.find { + (it as? JKField)?.name?.value == fieldTarget.name.value + } ?: continue + parameter.modifierList = (fieldDeclaration as JKField).modifierList.also { it.detach(it.parent!!) } + containingClass.declarationList -= fieldDeclaration + + if (parameter.name.value != fieldTarget.name.value) { + parameter.name = JKNameIdentifierImpl(fieldTarget.name.value) + } + somethingChanged = true + } + } + } + + private fun JKJavaAssignmentExpression.smartField(): JKFieldAccessExpression? { + val field = this.field + return when (field) { + is JKQualifiedExpression -> + (field.selector as? JKFieldAccessExpression)?.takeIf { field.receiver is JKThisExpression } + is JKFieldAccessExpression -> field + else -> null + } + } +} diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/jk.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/jk.kt index 93244c7ccf6..ace96b2b94a 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/jk.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/jk.kt @@ -89,7 +89,7 @@ class JKParameterImpl( override var modifierList by child(modifierList) override var initializer by child(initializer) - override val name by child(name) + override var name by child(name) override var type by child(type) } @@ -218,7 +218,7 @@ class JKLocalVariableImpl(modifierList: JKModifierList, type: JKTypeElement, nam JKLocalVariable, JKBranchElementBase() { override var modifierList by child(modifierList) override var initializer by child(initializer) - override val name by child(name) + override var name by child(name) override val type by child(type) override fun accept(visitor: JKVisitor, data: D): R = visitor.visitLocalVariable(this, data) diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/jk.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/jk.kt index 655dbac310a..1b9995e5b82 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/jk.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/jk.kt @@ -66,7 +66,7 @@ interface JKMethod : JKDeclaration, JKModifierListOwner { interface JKField : JKDeclaration, JKModifierListOwner { val type: JKTypeElement - val name: JKNameIdentifier + var name: JKNameIdentifier var initializer: JKExpression }