New J2K: Constructor conversion

This commit is contained in:
Simon Ogorodnik
2018-07-24 02:33:02 +03:00
committed by Ilya Kirillov
parent e83844e941
commit 6793c1d08f
11 changed files with 153 additions and 20 deletions
@@ -30,6 +30,7 @@ object ConversionsRunner {
AssignmentAsExpressionToAlsoConversion(context).runConversion(it, context)
AssignmentStatementValCreationConversion(context).runConversion(it, context)
AssignmentStatementOperatorConversion().runConversion(it, context)
ConstructorConversion().runConversion(it, context)
JavaMethodToKotlinFunctionConversion().runConversion(it, context)
LiteralConversion().runConversion(it, context)
InnerClassConversion().runConversion(it, context)
@@ -18,6 +18,8 @@ package org.jetbrains.kotlin.j2k
import com.intellij.lang.java.JavaLanguage
import com.intellij.psi.*
import com.intellij.psi.JavaTokenType.SUPER_KEYWORD
import com.intellij.psi.JavaTokenType.THIS_KEYWORD
import com.intellij.psi.impl.source.tree.ChildRole
import com.intellij.psi.impl.source.tree.java.PsiLiteralExpressionImpl
import com.intellij.psi.impl.source.tree.java.PsiNewExpressionImpl
@@ -129,11 +131,22 @@ class JavaToJKTreeBuilder(var symbolProvider: JKSymbolProvider) {
fun PsiMethodCallExpression.toJK(): JKExpression {
val method = methodExpression as PsiReferenceExpressionImpl
val call = JKJavaMethodCallExpressionImpl(symbolProvider.provideSymbol(method), argumentList.toJK())
return if (method.findChildByRole(ChildRole.DOT) != null) {
JKQualifiedExpressionImpl((method.qualifier as PsiExpression).toJK(), JKJavaQualifierImpl.DOT, call)
val referenceNameElement = methodExpression.referenceNameElement
val symbol = symbolProvider.provideSymbol<JKMethodSymbol>(method)
return if (referenceNameElement is PsiKeyword) {
val callee = when (referenceNameElement.tokenType) {
SUPER_KEYWORD -> JKSuperExpressionImpl()
THIS_KEYWORD -> JKThisExpressionImpl()
else -> error("Unknown keyword in callee position")
}
JKDelegationConstructorCallImpl(symbol, callee, argumentList.toJK())
} else {
call
val call = JKJavaMethodCallExpressionImpl(symbol, argumentList.toJK())
if (method.findChildByRole(ChildRole.DOT) != null) {
JKQualifiedExpressionImpl((method.qualifier as PsiExpression).toJK(), JKJavaQualifierImpl.DOT, call)
} else {
call
}
}
}
@@ -147,22 +147,22 @@ class NewCodeBuilder {
printer.printlnWithNoIndent()
}
override fun visitParameter(parameter: JKParameter) {
printer.printWithNoIndent(parameter.name.value, ": ")
parameter.type.accept(this)
if (parameter.initializer !is JKStubExpression) {
printer.printWithNoIndent(" = ")
parameter.initializer.accept(this)
}
}
override fun visitKtFunction(ktFunction: JKKtFunction) {
printer.printIndent()
ktFunction.modifierList.accept(this)
printer.printWithNoIndent(" fun ", ktFunction.name.value, "(")
for (parameter in ktFunction.parameters) {
if (parameter != ktFunction.parameters.first()) {
printer.printWithNoIndent(", ")
}
printer.printWithNoIndent(parameter.name.value, ": ")
parameter.type.accept(this)
if (parameter.initializer !is JKStubExpression) {
printer.printWithNoIndent(" = ")
parameter.initializer.accept(this)
}
renderList(ktFunction.parameters) {
it.accept(this)
}
printer.printWithNoIndent(")", ": ")
ktFunction.returnType.accept(this)
if (ktFunction.block !== JKBodyStub) {
@@ -222,6 +222,14 @@ class NewCodeBuilder {
prefixExpression.expression.accept(this)
}
override fun visitThisExpression(thisExpression: JKThisExpression) {
printer.printWithNoIndent("this")
}
override fun visitSuperExpression(superExpression: JKSuperExpression) {
printer.printWithNoIndent("super")
}
override fun visitPostfixExpression(postfixExpression: JKPostfixExpression) {
postfixExpression.expression.accept(this)
printer.printWithNoIndent(postfixExpression.operator.operatorText)
@@ -350,6 +358,31 @@ class NewCodeBuilder {
printer.par(SQUARE) { arrayAccessExpression.indexExpression.accept(this) }
}
override fun visitDelegationConstructorCall(delegationConstructorCall: JKDelegationConstructorCall) {
delegationConstructorCall.expression.accept(this)
printer.par {
delegationConstructorCall.arguments.accept(this)
}
}
override fun visitKtConstructor(ktConstructor: JKKtConstructor) {
printer.print("constructor")
printer.par(ROUND) {
renderList(ktConstructor.parameters) {
it.accept(this)
}
}
if (ktConstructor.delegationCall !is JKStubExpression) {
builder.append(" : ")
ktConstructor.delegationCall.accept(this)
}
if (ktConstructor.block !== JKBodyStub) {
printer.block(multiline = true) {
ktConstructor.block.accept(this)
}
}
}
private inline fun Printer.indented(block: () -> Unit) {
this.pushIndent()
block()
@@ -383,9 +416,9 @@ class NewCodeBuilder {
printer.printWithNoIndent(" }")
}
override fun visitParameter(parameter: JKParameter) {
/*override fun visitParameter(parameter: JKParameter) {
printer.printWithNoIndent(parameter.name.value)
}
}*/
override fun visitKtAssignmentStatement(ktAssignmentStatement: JKKtAssignmentStatement) {
ktAssignmentStatement.field.accept(this)
@@ -0,0 +1,12 @@
/*
* 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.JKElement
inline fun <reified T : JKElement> JKElement.parentOfType(): T? {
return generateSequence(parent) { it.parent }.filterIsInstance<T>().firstOrNull()
}
@@ -0,0 +1,31 @@
/*
* 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.*
class ConstructorConversion : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKJavaMethod) return recurse(element)
val outerClass = element.parentOfType<JKClass>() ?: return recurse(element)
if (element.name.value != outerClass.name.value) return recurse(element)
element.invalidate()
val delegationCall = lookupDelegationCall(element.block) ?: JKStubExpressionImpl()
return JKKtConstructorImpl(element.name, element.parameters, element.block, element.modifierList, delegationCall)
}
private fun lookupDelegationCall(block: JKBlock): JKDelegationConstructorCall? {
val firstStatement = block.statements.firstOrNull() ?: return null
val expressionStatement = firstStatement as? JKExpressionStatement ?: return null
val expression = expressionStatement.expression as? JKDelegationConstructorCall ?: return null
block.statements -= expressionStatement
expressionStatement.invalidate()
return expression
}
}
@@ -327,4 +327,15 @@ class JKInheritanceInfoImpl(implements: List<JKTypeElement>) : JKInheritanceInfo
override val inherit: List<JKTypeElement> by children(implements)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitInheritanceInfo(this, data)
}
}
class JKDelegationConstructorCallImpl(
override val identifier: JKMethodSymbol,
expression: JKExpression,
arguments: JKExpressionList
) : JKBranchElementBase(), JKDelegationConstructorCall {
override val expression: JKExpression by child(expression)
override val arguments: JKExpressionList by child(arguments)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitDelegationConstructorCall(this, data)
}
@@ -166,4 +166,22 @@ class JKKtAssignmentStatementImpl(
override var expression by child(expression)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitKtAssignmentStatement(this, data)
}
class JKKtConstructorImpl(
name: JKNameIdentifier,
parameters: List<JKParameter>,
block: JKBlock,
modifierList: JKModifierList,
delegationCall: JKExpression
) : JKBranchElementBase(), JKKtConstructor {
override val returnType: JKTypeElement get() = TODO("!")
override var name: JKNameIdentifier by child(name)
override var parameters: List<JKParameter> by children(parameters)
override var block: JKBlock by child(block)
override var modifierList: JKModifierList by child(modifierList)
override var delegationCall: JKExpression by child(delegationCall)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitKtConstructor(this, data)
}
@@ -108,7 +108,7 @@ interface JKNameIdentifier : JKIdentifier {
interface JKExpression : JKTreeElement
interface JKExpressionStatement : JKStatement {
interface JKExpressionStatement : JKBranchElement, JKStatement {
val expression: JKExpression
}
@@ -241,4 +241,10 @@ interface JKLambdaExpression : JKExpression {
var parameters: List<JKParameter>
val returnType: JKTypeElement
var statement: JKStatement
}
interface JKDelegationConstructorCall : JKMethodCallExpression {
override val identifier: JKMethodSymbol
val expression: JKExpression
override val arguments: JKExpressionList
}
@@ -25,7 +25,12 @@ interface JKKtFunction : JKMethod {
val block: JKBlock
}
interface JKKtConstructor : JKDeclaration
interface JKKtConstructor : JKDeclaration, JKModifierListOwner, JKMethod {
override var name: JKNameIdentifier
override var parameters: List<JKParameter>
var block: JKBlock
var delegationCall: JKExpression
}
interface JKKtPrimaryConstructor : JKKtConstructor
@@ -54,6 +54,7 @@ interface JKVisitor<out R, in D> {
fun visitIfElseExpression(ifElseExpression: JKIfElseExpression, data: D): R = visitExpression(ifElseExpression, data)
fun visitAssignableExpression(assignableExpression: JKAssignableExpression, data: D): R = visitExpression(assignableExpression, data)
fun visitLambdaExpression(lambdaExpression: JKLambdaExpression, data: D): R = visitExpression(lambdaExpression, data)
fun visitDelegationConstructorCall(delegationConstructorCall: JKDelegationConstructorCall, data: D): R = visitMethodCallExpression(delegationConstructorCall, data)
fun visitJavaField(javaField: JKJavaField, data: D): R = visitField(javaField, data)
fun visitJavaMethod(javaMethod: JKJavaMethod, data: D): R = visitMethod(javaMethod, data)
fun visitJavaMethodCallExpression(javaMethodCallExpression: JKJavaMethodCallExpression, data: D): R = visitMethodCallExpression(javaMethodCallExpression, data)
@@ -105,6 +105,8 @@ interface JKVisitorVoid : JKVisitor<Unit, Nothing?> {
override fun visitAssignableExpression(assignableExpression: JKAssignableExpression, data: Nothing?) = visitAssignableExpression(assignableExpression)
fun visitLambdaExpression(lambdaExpression: JKLambdaExpression) = visitExpression(lambdaExpression, null)
override fun visitLambdaExpression(lambdaExpression: JKLambdaExpression, data: Nothing?) = visitLambdaExpression(lambdaExpression)
fun visitDelegationConstructorCall(delegationConstructorCall: JKDelegationConstructorCall) = visitMethodCallExpression(delegationConstructorCall, null)
override fun visitDelegationConstructorCall(delegationConstructorCall: JKDelegationConstructorCall, data: Nothing?) = visitDelegationConstructorCall(delegationConstructorCall)
fun visitJavaField(javaField: JKJavaField) = visitField(javaField, null)
override fun visitJavaField(javaField: JKJavaField, data: Nothing?) = visitJavaField(javaField)
fun visitJavaMethod(javaMethod: JKJavaMethod) = visitMethod(javaMethod, null)