Java to Kotlin converter: converting usages of Kotlin properties from Java
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
<orderEntry type="module" module-name="util" />
|
||||
<orderEntry type="module" module-name="descriptor.loader.java" />
|
||||
<orderEntry type="library" name="idea-full" level="project" />
|
||||
<orderEntry type="module" module-name="frontend.java" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
|
||||
@@ -160,7 +160,7 @@ public class Converter(val project: Project, val settings: ConverterSettings) {
|
||||
var keepStatement = true
|
||||
if (statement is AssignmentExpression) {
|
||||
val assignee = statement.left
|
||||
if (assignee is CallChainExpression) {
|
||||
if (assignee is QualifiedExpression) {
|
||||
for (field in finalOrWithEmptyInitializerFields) {
|
||||
val id = field.identifier.toKotlin()
|
||||
if (assignee.identifier.toKotlin().endsWith("." + id)) {
|
||||
@@ -600,8 +600,8 @@ public class Converter(val project: Project, val settings: ConverterSettings) {
|
||||
private fun convertToNotNullableTypes(types: Array<out PsiType?>): List<Type>
|
||||
= types.map { convertType(it, Nullability.NotNull) }
|
||||
|
||||
public fun convertParameterList(parameters: PsiParameterList): ParameterList
|
||||
= ParameterList(parameters.getParameters().map { convertParameter(it) })
|
||||
public fun convertParameterList(parameterList: PsiParameterList): ParameterList
|
||||
= ParameterList(parameterList.getParameters().map { convertParameter(it) })
|
||||
|
||||
public fun convertParameter(parameter: PsiParameter,
|
||||
nullability: Nullability = Nullability.Default,
|
||||
|
||||
@@ -36,7 +36,7 @@ open class MethodCallExpression(
|
||||
|
||||
class object {
|
||||
fun build(receiver: Expression, methodName: String, arguments: List<Expression> = ArrayList()): MethodCallExpression {
|
||||
return MethodCallExpression(CallChainExpression(receiver, Identifier(methodName, false)),
|
||||
return MethodCallExpression(QualifiedExpression(receiver, Identifier(methodName, false)),
|
||||
arguments,
|
||||
ArrayList(), false)
|
||||
}
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@
|
||||
|
||||
package org.jetbrains.jet.j2k.ast
|
||||
|
||||
class CallChainExpression(val expression: Expression, val identifier: Expression) : Expression() {
|
||||
class QualifiedExpression(val expression: Expression, val identifier: Expression) : Expression() {
|
||||
override val isNullable: Boolean
|
||||
get() {
|
||||
if (!expression.isEmpty && expression.isNullable) return true
|
||||
@@ -25,6 +25,8 @@ import com.intellij.psi.CommonClassNames.*
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.jet.lang.types.lang.PrimitiveType
|
||||
import org.jetbrains.jet.j2k.*
|
||||
import org.jetbrains.jet.lang.resolve.java.jetAsJava.KotlinLightMethod
|
||||
import org.jetbrains.jet.lang.psi.JetProperty
|
||||
|
||||
open class ExpressionVisitor(protected val converter: Converter,
|
||||
private val usageReplacementMap: Map<PsiVariable, String> = mapOf()) : JavaElementVisitor() {
|
||||
@@ -75,8 +77,7 @@ open class ExpressionVisitor(protected val converter: Converter,
|
||||
result = MethodCallExpression.build(lhs, "ushr", listOf(rhs))
|
||||
}
|
||||
else {
|
||||
result = BinaryExpression(lhs, rhs,
|
||||
getOperatorString(expression.getOperationSign().getTokenType()))
|
||||
result = BinaryExpression(lhs, rhs, getOperatorString(expression.getOperationSign().getTokenType()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,15 +138,38 @@ open class ExpressionVisitor(protected val converter: Converter,
|
||||
}
|
||||
|
||||
override fun visitMethodCallExpression(expression: PsiMethodCallExpression) {
|
||||
convertMethodCallExpression(expression)
|
||||
}
|
||||
val methodExpr = expression.getMethodExpression()
|
||||
val target = methodExpr.resolve()
|
||||
if (target is KotlinLightMethod) {
|
||||
val property = target.origin as? JetProperty
|
||||
if (property != null) {
|
||||
val parameterCount = target.getParameterList().getParameters().size
|
||||
val argCount = expression.getArgumentList().getExpressions().size
|
||||
if (parameterCount == argCount) {
|
||||
val qualifier = converter.convertExpression(methodExpr.getQualifierExpression())
|
||||
val propertyName = Identifier(property.getName()!!, false)
|
||||
val propertyAccess = QualifiedExpression(qualifier, propertyName)
|
||||
when(parameterCount) {
|
||||
0 /* getter */ -> {
|
||||
result = propertyAccess
|
||||
return
|
||||
}
|
||||
|
||||
1 /* setter */ -> {
|
||||
val argument = converter.convertExpression(expression.getArgumentList().getExpressions().single())
|
||||
result = AssignmentExpression(propertyAccess, argument, "=")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected fun convertMethodCallExpression(expression: PsiMethodCallExpression) {
|
||||
if (!expression.isSuperConstructorCall() || !expression.isInsidePrimaryConstructor()) {
|
||||
result = MethodCallExpression(converter.convertExpression(expression.getMethodExpression()),
|
||||
converter.convertArguments(expression),
|
||||
converter.convertTypes(expression.getTypeArguments()),
|
||||
converter.convertType(expression.getType()).isNullable)
|
||||
result = MethodCallExpression(converter.convertExpression(methodExpr),
|
||||
converter.convertArguments(expression),
|
||||
converter.convertTypes(expression.getTypeArguments()),
|
||||
converter.convertType(expression.getType()).isNullable)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,7 +201,7 @@ open class ExpressionVisitor(protected val converter: Converter,
|
||||
|
||||
val reference = expression.getClassReference()
|
||||
val typeParameters = if (reference != null) converter.convertTypes(reference.getTypeParameters()) else listOf()
|
||||
return CallChainExpression(Identifier(constructor.getName(), false),
|
||||
return QualifiedExpression(Identifier(constructor.getName(), false),
|
||||
MethodCallExpression(Identifier("init"), converter.convertExpressions(arguments), typeParameters, false))
|
||||
}
|
||||
|
||||
@@ -222,7 +246,7 @@ open class ExpressionVisitor(protected val converter: Converter,
|
||||
val qualifier = expression.getQualifierExpression()
|
||||
|
||||
if (addReceiver) {
|
||||
identifier = CallChainExpression(Identifier("__", false), Identifier(referencedName, isNullable))
|
||||
identifier = QualifiedExpression(Identifier("__", false), Identifier(referencedName, isNullable))
|
||||
}
|
||||
else if (insideSecondaryConstructor && expression.isThisConstructorCall()) {
|
||||
identifier = Identifier("val __ = " + (containingConstructor?.getContainingClass()?.getNameIdentifier()?.getText() ?: ""))
|
||||
@@ -263,7 +287,7 @@ open class ExpressionVisitor(protected val converter: Converter,
|
||||
}
|
||||
}
|
||||
|
||||
result = CallChainExpression(converter.convertExpression(qualifier), identifier)
|
||||
result = QualifiedExpression(converter.convertExpression(qualifier), identifier)
|
||||
}
|
||||
|
||||
private fun PsiReference.nullability(): Nullability {
|
||||
|
||||
@@ -32,10 +32,22 @@ import com.intellij.psi.codeStyle.CodeStyleManager
|
||||
import org.jetbrains.jet.JetTestUtils
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.command.WriteCommandAction
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
|
||||
abstract class AbstractJavaToKotlinConverterTest() : LightIdeaTestCase() {
|
||||
val testHeaderPattern = Pattern.compile("//(element|expression|statement|method|class|file|comp)\n")
|
||||
|
||||
override fun setUp() {
|
||||
super.setUp()
|
||||
|
||||
ApplicationManager.getApplication()!!.runWriteAction{
|
||||
val kotlinApiFileName = "KotlinApi.kt"
|
||||
val kotlinCode = FileUtil.loadFile(File("j2k/tests/testData/$kotlinApiFileName"), true)
|
||||
val kotlinFile = LightPlatformTestCase.getSourceRoot()!!.createChildData(null, kotlinApiFileName)!!
|
||||
kotlinFile.getOutputStream(null)!!.writer().use { it.write(kotlinCode) }
|
||||
}
|
||||
}
|
||||
|
||||
public fun doTest(javaPath: String) {
|
||||
val project = LightPlatformTestCase.getProject()!!
|
||||
val javaFile = File(javaPath)
|
||||
|
||||
@@ -31,7 +31,7 @@ import org.jetbrains.jet.j2k.test.AbstractJavaToKotlinConverterTest;
|
||||
/** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("j2k/tests/testData/ast")
|
||||
@InnerTestClasses({JavaToKotlinConverterTestGenerated.Annotations.class, JavaToKotlinConverterTestGenerated.AnonymousBlock.class, JavaToKotlinConverterTestGenerated.ArrayAccessExpression.class, JavaToKotlinConverterTestGenerated.ArrayInitializerExpression.class, JavaToKotlinConverterTestGenerated.ArrayType.class, JavaToKotlinConverterTestGenerated.AssertStatement.class, JavaToKotlinConverterTestGenerated.AssignmentExpression.class, JavaToKotlinConverterTestGenerated.BinaryExpression.class, JavaToKotlinConverterTestGenerated.BoxedType.class, JavaToKotlinConverterTestGenerated.BreakStatement.class, JavaToKotlinConverterTestGenerated.CallChainExpression.class, JavaToKotlinConverterTestGenerated.Class.class, JavaToKotlinConverterTestGenerated.ClassExpression.class, JavaToKotlinConverterTestGenerated.ConditionalExpression.class, JavaToKotlinConverterTestGenerated.Constructors.class, JavaToKotlinConverterTestGenerated.ContinueStatement.class, JavaToKotlinConverterTestGenerated.DeclarationStatement.class, JavaToKotlinConverterTestGenerated.DoWhileStatement.class, JavaToKotlinConverterTestGenerated.Enum.class, JavaToKotlinConverterTestGenerated.Field.class, JavaToKotlinConverterTestGenerated.For.class, JavaToKotlinConverterTestGenerated.ForeachStatement.class, JavaToKotlinConverterTestGenerated.Formatting.class, JavaToKotlinConverterTestGenerated.Function.class, JavaToKotlinConverterTestGenerated.Identifier.class, JavaToKotlinConverterTestGenerated.IfStatement.class, JavaToKotlinConverterTestGenerated.ImportStatement.class, JavaToKotlinConverterTestGenerated.InProjectionType.class, JavaToKotlinConverterTestGenerated.Inheritance.class, JavaToKotlinConverterTestGenerated.IsOperator.class, JavaToKotlinConverterTestGenerated.Issues.class, JavaToKotlinConverterTestGenerated.KotlinExclusion.class, JavaToKotlinConverterTestGenerated.LabelStatement.class, JavaToKotlinConverterTestGenerated.List.class, JavaToKotlinConverterTestGenerated.LiteralExpression.class, JavaToKotlinConverterTestGenerated.LocalVariable.class, JavaToKotlinConverterTestGenerated.MethodCallExpression.class, JavaToKotlinConverterTestGenerated.Misc.class, JavaToKotlinConverterTestGenerated.NewClassExpression.class, JavaToKotlinConverterTestGenerated.Nullability.class, JavaToKotlinConverterTestGenerated.ObjectLiteral.class, JavaToKotlinConverterTestGenerated.OutProjectionType.class, JavaToKotlinConverterTestGenerated.PackageStatement.class, JavaToKotlinConverterTestGenerated.ParenthesizedExpression.class, JavaToKotlinConverterTestGenerated.PolyadicExpression.class, JavaToKotlinConverterTestGenerated.PostfixOperator.class, JavaToKotlinConverterTestGenerated.PrefixOperator.class, JavaToKotlinConverterTestGenerated.RawGenerics.class, JavaToKotlinConverterTestGenerated.ReturnStatement.class, JavaToKotlinConverterTestGenerated.Settings.class, JavaToKotlinConverterTestGenerated.StarProjectionType.class, JavaToKotlinConverterTestGenerated.SuperExpression.class, JavaToKotlinConverterTestGenerated.Switch.class, JavaToKotlinConverterTestGenerated.SynchronizedStatement.class, JavaToKotlinConverterTestGenerated.ThisExpression.class, JavaToKotlinConverterTestGenerated.ThrowStatement.class, JavaToKotlinConverterTestGenerated.Trait.class, JavaToKotlinConverterTestGenerated.TryStatement.class, JavaToKotlinConverterTestGenerated.TypeCastExpression.class, JavaToKotlinConverterTestGenerated.TypeParameters.class, JavaToKotlinConverterTestGenerated.VarArg.class, JavaToKotlinConverterTestGenerated.WhileStatement.class})
|
||||
@InnerTestClasses({JavaToKotlinConverterTestGenerated.Annotations.class, JavaToKotlinConverterTestGenerated.AnonymousBlock.class, JavaToKotlinConverterTestGenerated.ArrayAccessExpression.class, JavaToKotlinConverterTestGenerated.ArrayInitializerExpression.class, JavaToKotlinConverterTestGenerated.ArrayType.class, JavaToKotlinConverterTestGenerated.AssertStatement.class, JavaToKotlinConverterTestGenerated.AssignmentExpression.class, JavaToKotlinConverterTestGenerated.BinaryExpression.class, JavaToKotlinConverterTestGenerated.BoxedType.class, JavaToKotlinConverterTestGenerated.BreakStatement.class, JavaToKotlinConverterTestGenerated.CallChainExpression.class, JavaToKotlinConverterTestGenerated.Class.class, JavaToKotlinConverterTestGenerated.ClassExpression.class, JavaToKotlinConverterTestGenerated.ConditionalExpression.class, JavaToKotlinConverterTestGenerated.Constructors.class, JavaToKotlinConverterTestGenerated.ContinueStatement.class, JavaToKotlinConverterTestGenerated.DeclarationStatement.class, JavaToKotlinConverterTestGenerated.DoWhileStatement.class, JavaToKotlinConverterTestGenerated.Enum.class, JavaToKotlinConverterTestGenerated.Field.class, JavaToKotlinConverterTestGenerated.For.class, JavaToKotlinConverterTestGenerated.ForeachStatement.class, JavaToKotlinConverterTestGenerated.Formatting.class, JavaToKotlinConverterTestGenerated.Function.class, JavaToKotlinConverterTestGenerated.Identifier.class, JavaToKotlinConverterTestGenerated.IfStatement.class, JavaToKotlinConverterTestGenerated.ImportStatement.class, JavaToKotlinConverterTestGenerated.InProjectionType.class, JavaToKotlinConverterTestGenerated.Inheritance.class, JavaToKotlinConverterTestGenerated.IsOperator.class, JavaToKotlinConverterTestGenerated.Issues.class, JavaToKotlinConverterTestGenerated.KotlinApiAccess.class, JavaToKotlinConverterTestGenerated.KotlinExclusion.class, JavaToKotlinConverterTestGenerated.LabelStatement.class, JavaToKotlinConverterTestGenerated.List.class, JavaToKotlinConverterTestGenerated.LiteralExpression.class, JavaToKotlinConverterTestGenerated.LocalVariable.class, JavaToKotlinConverterTestGenerated.MethodCallExpression.class, JavaToKotlinConverterTestGenerated.Misc.class, JavaToKotlinConverterTestGenerated.NewClassExpression.class, JavaToKotlinConverterTestGenerated.Nullability.class, JavaToKotlinConverterTestGenerated.ObjectLiteral.class, JavaToKotlinConverterTestGenerated.OutProjectionType.class, JavaToKotlinConverterTestGenerated.PackageStatement.class, JavaToKotlinConverterTestGenerated.ParenthesizedExpression.class, JavaToKotlinConverterTestGenerated.PolyadicExpression.class, JavaToKotlinConverterTestGenerated.PostfixOperator.class, JavaToKotlinConverterTestGenerated.PrefixOperator.class, JavaToKotlinConverterTestGenerated.RawGenerics.class, JavaToKotlinConverterTestGenerated.ReturnStatement.class, JavaToKotlinConverterTestGenerated.Settings.class, JavaToKotlinConverterTestGenerated.StarProjectionType.class, JavaToKotlinConverterTestGenerated.SuperExpression.class, JavaToKotlinConverterTestGenerated.Switch.class, JavaToKotlinConverterTestGenerated.SynchronizedStatement.class, JavaToKotlinConverterTestGenerated.ThisExpression.class, JavaToKotlinConverterTestGenerated.ThrowStatement.class, JavaToKotlinConverterTestGenerated.Trait.class, JavaToKotlinConverterTestGenerated.TryStatement.class, JavaToKotlinConverterTestGenerated.TypeCastExpression.class, JavaToKotlinConverterTestGenerated.TypeParameters.class, JavaToKotlinConverterTestGenerated.VarArg.class, JavaToKotlinConverterTestGenerated.WhileStatement.class})
|
||||
public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConverterTest {
|
||||
public void testAllFilesPresentInAst() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("j2k/tests/testData/ast"), Pattern.compile("^(.+)\\.java$"), true);
|
||||
@@ -1550,6 +1550,24 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv
|
||||
|
||||
}
|
||||
|
||||
@TestMetadata("j2k/tests/testData/ast/kotlinApiAccess")
|
||||
public static class KotlinApiAccess extends AbstractJavaToKotlinConverterTest {
|
||||
public void testAllFilesPresentInKotlinApiAccess() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("j2k/tests/testData/ast/kotlinApiAccess"), Pattern.compile("^(.+)\\.java$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("InheritedProperty.java")
|
||||
public void testInheritedProperty() throws Exception {
|
||||
doTest("j2k/tests/testData/ast/kotlinApiAccess/InheritedProperty.java");
|
||||
}
|
||||
|
||||
@TestMetadata("Property.java")
|
||||
public void testProperty() throws Exception {
|
||||
doTest("j2k/tests/testData/ast/kotlinApiAccess/Property.java");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@TestMetadata("j2k/tests/testData/ast/kotlinExclusion")
|
||||
public static class KotlinExclusion extends AbstractJavaToKotlinConverterTest {
|
||||
public void testAllFilesPresentInKotlinExclusion() throws Exception {
|
||||
@@ -2497,6 +2515,7 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv
|
||||
suite.addTestSuite(Inheritance.class);
|
||||
suite.addTestSuite(IsOperator.class);
|
||||
suite.addTestSuite(Issues.class);
|
||||
suite.addTestSuite(KotlinApiAccess.class);
|
||||
suite.addTestSuite(KotlinExclusion.class);
|
||||
suite.addTestSuite(LabelStatement.class);
|
||||
suite.addTestSuite(List.class);
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
package kotlinApi
|
||||
|
||||
public open class KotlinClass {
|
||||
public var property: String
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
//file
|
||||
import kotlinApi.*
|
||||
|
||||
class C extends KotlinClass {
|
||||
void foo() {
|
||||
System.out.println(getProperty());
|
||||
setProperty("a")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import kotlinApi.*
|
||||
|
||||
class C() : KotlinClass() {
|
||||
fun foo() {
|
||||
System.out.println(property)
|
||||
property = "a"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
//file
|
||||
import kotlinApi.*
|
||||
|
||||
class C {
|
||||
void foo(KotlinClass k) {
|
||||
System.out.println(k.getProperty());
|
||||
k.setProperty("a")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import kotlinApi.*
|
||||
|
||||
class C() {
|
||||
fun foo(k: KotlinClass) {
|
||||
System.out.println(k.property)
|
||||
k.property = "a"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user