diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/ConversionsRunner.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/ConversionsRunner.kt index f6e670c45d9..5c12cab3909 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/ConversionsRunner.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/ConversionsRunner.kt @@ -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) diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/JavaToJKTreeBuilder.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/JavaToJKTreeBuilder.kt index c2abd746cf6..9428f839248 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/JavaToJKTreeBuilder.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/JavaToJKTreeBuilder.kt @@ -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(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 + } } } diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/NewCodeBuilder.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/NewCodeBuilder.kt index b732b335441..d0c07560f55 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/NewCodeBuilder.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/NewCodeBuilder.kt @@ -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) diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/ASTWalk.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/ASTWalk.kt new file mode 100644 index 00000000000..a8f1922b87d --- /dev/null +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/ASTWalk.kt @@ -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 JKElement.parentOfType(): T? { + return generateSequence(parent) { it.parent }.filterIsInstance().firstOrNull() +} \ No newline at end of file diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/ConstructorConversion.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/ConstructorConversion.kt new file mode 100644 index 00000000000..9a6a77000ca --- /dev/null +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/ConstructorConversion.kt @@ -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() ?: 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 + } +} \ No newline at end of file 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 2c93266b0a1..e0dfdc28c9f 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/jk.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/jk.kt @@ -327,4 +327,15 @@ class JKInheritanceInfoImpl(implements: List) : JKInheritanceInfo override val inherit: List by children(implements) override fun accept(visitor: JKVisitor, data: D): R = visitor.visitInheritanceInfo(this, data) -} \ No newline at end of file +} + +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 accept(visitor: JKVisitor, data: D): R = visitor.visitDelegationConstructorCall(this, data) +} diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/k.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/k.kt index 902a58c3357..772a6a7af0d 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/k.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/k.kt @@ -166,4 +166,22 @@ class JKKtAssignmentStatementImpl( override var expression by child(expression) override fun accept(visitor: JKVisitor, data: D): R = visitor.visitKtAssignmentStatement(this, data) +} + +class JKKtConstructorImpl( + name: JKNameIdentifier, + parameters: List, + 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 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 accept(visitor: JKVisitor, data: D): R = visitor.visitKtConstructor(this, data) } \ No newline at end of file diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/jk.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/jk.kt index 3b24efb62cd..0630af03de6 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/jk.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/jk.kt @@ -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 val returnType: JKTypeElement var statement: JKStatement +} + +interface JKDelegationConstructorCall : JKMethodCallExpression { + override val identifier: JKMethodSymbol + val expression: JKExpression + override val arguments: JKExpressionList } \ No newline at end of file diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/k.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/k.kt index c5beac8d4fa..1abf093ffd2 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/k.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/k.kt @@ -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 + var block: JKBlock + var delegationCall: JKExpression +} interface JKKtPrimaryConstructor : JKKtConstructor diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/visitors/JKVisitor.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/visitors/JKVisitor.kt index 14b598c51ed..ea54d127301 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/visitors/JKVisitor.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/visitors/JKVisitor.kt @@ -54,6 +54,7 @@ interface JKVisitor { 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) diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/visitors/JKVisitorVoid.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/visitors/JKVisitorVoid.kt index 330049b43a6..c4dcf95956c 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/visitors/JKVisitorVoid.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/visitors/JKVisitorVoid.kt @@ -105,6 +105,8 @@ interface JKVisitorVoid : JKVisitor { 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)