Java to Kotlin converter: refactored code moving all knowledge about factory function internals into ConstructorConverter

This commit is contained in:
Valentin Kipyatkov
2014-06-25 21:29:29 +04:00
parent 1e15727387
commit 3ebc8046a9
3 changed files with 32 additions and 49 deletions
@@ -37,7 +37,21 @@ class ConstructorConverter(private val converter: Converter) {
}
else {
val params = converter.convertParameterList(constructor.getParameterList())
var body = postProcessBody(converter.convertBlock(constructor.getBody()))
val bodyConverter = converter.withExpressionVisitor { object : ExpressionVisitor(it, mapOf()/*TODO: see KT-5327*/) {
override fun visitReferenceExpression(expression: PsiReferenceExpression) {
if (isQualifierEmptyOrThis(expression)) {
val field = expression.getReference()?.resolve() as? PsiField
if (field != null && field.getContainingClass() == constructor.getContainingClass()) {
val isNullable = typeConverter.variableNullability(field).isNullable(converter.settings)
result = QualifiedExpression(tempValIdentifier(), Identifier(expression.getReferenceName()!!, isNullable).assignNoPrototype())
return
}
}
super.visitReferenceExpression(expression)
}
}}
var body = postProcessBody(bodyConverter.convertBlock(constructor.getBody()))
val containingClass = constructor.getContainingClass()
val typeParameterList = converter.convertTypeParameterList(containingClass?.getTypeParameterList())
val factoryFunctionType = ClassType(containingClass?.declarationIdentifier() ?: Identifier.Empty,
@@ -84,8 +98,8 @@ class ConstructorConverter(private val converter: Converter) {
}
}
val correctedConverter = converter.withExpressionVisitor { ExpressionVisitor(it, usageReplacementMap) }
postProcessBody(correctedConverter.convertBlock(body, false, { !statementsToRemove.contains(it) }))
val bodyConverter = converter.withExpressionVisitor { ExpressionVisitor(it, usageReplacementMap) }
postProcessBody(bodyConverter.convertBlock(body, false, { !statementsToRemove.contains(it) }))
}
else {
Block.Empty
@@ -163,7 +177,7 @@ class ConstructorConverter(private val converter: Converter) {
var keepStatement = true
if (statement is AssignmentExpression) {
val assignee = statement.left
if (assignee is QualifiedExpression && (assignee.qualifier as? Identifier)?.name == FactoryFunction.tempValName) {
if (assignee is QualifiedExpression && (assignee.qualifier as? Identifier)?.name == tempValName) {
val name = (assignee.identifier as Identifier).name
for (field in finalOrWithEmptyInitializerFields) {
if (name == field.identifier.name) {
@@ -185,14 +199,14 @@ class ConstructorConverter(private val converter: Converter) {
className.name,
finalOrWithEmptyInitializerFields.map { initializers[it]!! }).assignNoPrototype()
if (statements.isNotEmpty()) {
val localVar = LocalVariable(FactoryFunction.tempValIdentifier(),
val localVar = LocalVariable(tempValIdentifier(),
Annotations.Empty,
Modifiers.Empty,
null,
initializer,
true).assignNoPrototype()
statements.add(0, DeclarationStatement(listOf(localVar)).assignNoPrototype())
statements.add(ReturnStatement(FactoryFunction.tempValIdentifier()).assignNoPrototype())
statements.add(ReturnStatement(tempValIdentifier()).assignNoPrototype())
}
else {
statements.add(ReturnStatement(initializer).assignNoPrototype())
@@ -235,16 +249,19 @@ class ConstructorConverter(private val converter: Converter) {
statements[i] = ReturnStatement(constructorCall).assignNoPrototype()
return statements
}
val localVar = LocalVariable(FactoryFunction.tempValIdentifier(), Annotations.Empty, Modifiers.Empty, null, constructorCall, true).assignNoPrototype()
val localVar = LocalVariable(tempValIdentifier(), Annotations.Empty, Modifiers.Empty, null, constructorCall, true).assignNoPrototype()
statements[i] = DeclarationStatement(listOf(localVar)).assignNoPrototype()
break
}
}
}
statements.add(ReturnStatement(FactoryFunction.tempValIdentifier()).assignNoPrototype())
statements.add(ReturnStatement(tempValIdentifier()).assignNoPrototype())
return statements
}
private fun ClassBody.factoryFunctions() = classObjectMembers.filterIsInstance(javaClass<FactoryFunction>())
private val tempValName: String = "__"
private fun tempValIdentifier(): Identifier = Identifier(tempValName, false).assignNoPrototype()
}
@@ -58,28 +58,4 @@ class FactoryFunction(annotations: Annotations,
parameterList: ParameterList,
typeParameterList: TypeParameterList,
block: Block)
: Function(Identifier("create").assignNoPrototype(), annotations, modifiers, returnType, typeParameterList, parameterList, block, false) {
/*
public fun toFactoryFunction(containingClass: Class?): Function {
val statements = ArrayList(block?.statements ?: listOf())
statements.add(ReturnStatement(tempValIdentifier()).assignNoPrototype())
val newBlock = Block(statements, block?.lBrace ?: LBrace().assignNoPrototype(), block?.rBrace ?: RBrace().assignNoPrototype())
if (block != null) {
newBlock.assignPrototypesFrom(block!!)
}
val typeParameters = if (containingClass != null) containingClass.typeParameterList.parameters else listOf()
val typeParameterList = TypeParameterList(typeParameters).assignNoPrototype()
val returnType = ClassType(containingClass?.name ?: Identifier.Empty, typeParameters, Nullability.NotNull, converter.settings).assignNoPrototype()
return Function(converter, Identifier("create").assignNoPrototype(), annotations, modifiers,
returnType, typeParameterList, parameterList, newBlock, false).assignPrototypesFrom(this)
}
*/
class object {
public val tempValName: String = "__"
public fun tempValIdentifier(): Identifier = Identifier(tempValName, false).assignNoPrototype()
}
}
: Function(Identifier("create").assignNoPrototype(), annotations, modifiers, returnType, typeParameterList, parameterList, block, false)
@@ -36,7 +36,7 @@ import org.jetbrains.jet.lang.resolve.java.JvmAbi
import org.jetbrains.jet.lang.psi.JetParameter
import org.jetbrains.jet.lang.psi.JetNamedDeclaration
class ExpressionVisitor(private val converter: Converter,
open class ExpressionVisitor(private val converter: Converter,
private val usageReplacementMap: Map<PsiVariable, String> = mapOf()) : JavaElementVisitor() {
private val typeConverter = converter.typeConverter
@@ -308,27 +308,17 @@ class ExpressionVisitor(private val converter: Converter,
}
override fun visitReferenceExpression(expression: PsiReferenceExpression) {
val referencedName = expression.getReferenceName()!!
val referenceName = expression.getReferenceName()!!
val target = expression.getReference()?.resolve()
val isNullable = if (target is PsiVariable) typeConverter.variableNullability(target).isNullable(converter.settings) else false
val containingConstructor = expression.getContainingConstructor()
val insideSecondaryConstructor = containingConstructor != null && !containingConstructor.isPrimaryConstructor()
if (insideSecondaryConstructor &&
isQualifierEmptyOrThis(expression) &&
(expression.getReference()?.resolve() as? PsiField)?.getContainingClass() == containingConstructor!!.getContainingClass()) {
result = QualifiedExpression(FactoryFunction.tempValIdentifier(), Identifier(referencedName, isNullable).assignNoPrototype())
return
}
var identifier = Identifier(referencedName, isNullable).assignNoPrototype()
val qualifier = expression.getQualifierExpression()
if (qualifier != null && qualifier.getType() is PsiArrayType && referencedName == "length") {
var identifier = Identifier(referenceName, isNullable).assignNoPrototype()
if (qualifier != null && qualifier.getType() is PsiArrayType && referenceName == "length") {
identifier = Identifier("size", isNullable).assignNoPrototype()
}
else if (qualifier != null) {
if (referencedName == JvmAbi.CLASS_OBJECT_FIELD || referencedName == JvmAbi.INSTANCE_FIELD) {
if (referenceName == JvmAbi.CLASS_OBJECT_FIELD || referenceName == JvmAbi.INSTANCE_FIELD) {
if (target is LightField) { //TODO: should be KotlinLightField with check of origin here, see KT-5188
result = converter.convertExpression(qualifier)
return
@@ -349,7 +339,7 @@ class ExpressionVisitor(private val converter: Converter,
&& !PsiTreeUtil.isAncestor(target.getContainingClass(), expression, true)
&& !isStaticallyImported(target, expression)) {
var member: PsiMember = target
var code = Identifier.toKotlin(referencedName)
var code = Identifier.toKotlin(referenceName)
while (member.getContainingClass() != null) {
code = Identifier.toKotlin(member.getContainingClass()!!.getName()!!) + "." + code
member = member.getContainingClass()!!