diff --git a/j2k/j2k.iml b/j2k/j2k.iml
index 41c3c2ee98c..a5e5d67ecd7 100644
--- a/j2k/j2k.iml
+++ b/j2k/j2k.iml
@@ -11,6 +11,7 @@
+
diff --git a/j2k/src/org/jetbrains/jet/j2k/Converter.kt b/j2k/src/org/jetbrains/jet/j2k/Converter.kt
index 63c20ab46be..aa4fd8fd8d8 100644
--- a/j2k/src/org/jetbrains/jet/j2k/Converter.kt
+++ b/j2k/src/org/jetbrains/jet/j2k/Converter.kt
@@ -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): List
= 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,
diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/MethodCallExpression.kt b/j2k/src/org/jetbrains/jet/j2k/ast/MethodCallExpression.kt
index 89c330f407f..fba0dda99fd 100644
--- a/j2k/src/org/jetbrains/jet/j2k/ast/MethodCallExpression.kt
+++ b/j2k/src/org/jetbrains/jet/j2k/ast/MethodCallExpression.kt
@@ -36,7 +36,7 @@ open class MethodCallExpression(
class object {
fun build(receiver: Expression, methodName: String, arguments: List = ArrayList()): MethodCallExpression {
- return MethodCallExpression(CallChainExpression(receiver, Identifier(methodName, false)),
+ return MethodCallExpression(QualifiedExpression(receiver, Identifier(methodName, false)),
arguments,
ArrayList(), false)
}
diff --git a/j2k/src/org/jetbrains/jet/j2k/ast/CallChainExpression.kt b/j2k/src/org/jetbrains/jet/j2k/ast/QualifiedExpression.kt
similarity index 94%
rename from j2k/src/org/jetbrains/jet/j2k/ast/CallChainExpression.kt
rename to j2k/src/org/jetbrains/jet/j2k/ast/QualifiedExpression.kt
index d18af29a2a6..0bfabe30f96 100644
--- a/j2k/src/org/jetbrains/jet/j2k/ast/CallChainExpression.kt
+++ b/j2k/src/org/jetbrains/jet/j2k/ast/QualifiedExpression.kt
@@ -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
diff --git a/j2k/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.kt b/j2k/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.kt
index d11d75331a4..93ce24e3765 100644
--- a/j2k/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.kt
+++ b/j2k/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.kt
@@ -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 = 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 {
diff --git a/j2k/tests/test/org/jetbrains/jet/j2k/test/AbstractJavaToKotlinConverterTest.kt b/j2k/tests/test/org/jetbrains/jet/j2k/test/AbstractJavaToKotlinConverterTest.kt
index 63363c814fd..b988bff7328 100644
--- a/j2k/tests/test/org/jetbrains/jet/j2k/test/AbstractJavaToKotlinConverterTest.kt
+++ b/j2k/tests/test/org/jetbrains/jet/j2k/test/AbstractJavaToKotlinConverterTest.kt
@@ -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)
diff --git a/j2k/tests/test/org/jetbrains/jet/j2k/test/JavaToKotlinConverterTestGenerated.java b/j2k/tests/test/org/jetbrains/jet/j2k/test/JavaToKotlinConverterTestGenerated.java
index 6b74bb3104b..3dcbfc9bb01 100644
--- a/j2k/tests/test/org/jetbrains/jet/j2k/test/JavaToKotlinConverterTestGenerated.java
+++ b/j2k/tests/test/org/jetbrains/jet/j2k/test/JavaToKotlinConverterTestGenerated.java
@@ -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);
diff --git a/j2k/tests/testData/KotlinApi.kt b/j2k/tests/testData/KotlinApi.kt
new file mode 100644
index 00000000000..2e026a7240e
--- /dev/null
+++ b/j2k/tests/testData/KotlinApi.kt
@@ -0,0 +1,5 @@
+package kotlinApi
+
+public open class KotlinClass {
+ public var property: String
+}
\ No newline at end of file
diff --git a/j2k/tests/testData/ast/kotlinApiAccess/InheritedProperty.java b/j2k/tests/testData/ast/kotlinApiAccess/InheritedProperty.java
new file mode 100644
index 00000000000..93ffccf2b02
--- /dev/null
+++ b/j2k/tests/testData/ast/kotlinApiAccess/InheritedProperty.java
@@ -0,0 +1,9 @@
+//file
+import kotlinApi.*
+
+class C extends KotlinClass {
+ void foo() {
+ System.out.println(getProperty());
+ setProperty("a")
+ }
+}
\ No newline at end of file
diff --git a/j2k/tests/testData/ast/kotlinApiAccess/InheritedProperty.kt b/j2k/tests/testData/ast/kotlinApiAccess/InheritedProperty.kt
new file mode 100644
index 00000000000..4fe3001a917
--- /dev/null
+++ b/j2k/tests/testData/ast/kotlinApiAccess/InheritedProperty.kt
@@ -0,0 +1,8 @@
+import kotlinApi.*
+
+class C() : KotlinClass() {
+ fun foo() {
+ System.out.println(property)
+ property = "a"
+ }
+}
\ No newline at end of file
diff --git a/j2k/tests/testData/ast/kotlinApiAccess/Property.java b/j2k/tests/testData/ast/kotlinApiAccess/Property.java
new file mode 100644
index 00000000000..396f99b1660
--- /dev/null
+++ b/j2k/tests/testData/ast/kotlinApiAccess/Property.java
@@ -0,0 +1,9 @@
+//file
+import kotlinApi.*
+
+class C {
+ void foo(KotlinClass k) {
+ System.out.println(k.getProperty());
+ k.setProperty("a")
+ }
+}
\ No newline at end of file
diff --git a/j2k/tests/testData/ast/kotlinApiAccess/Property.kt b/j2k/tests/testData/ast/kotlinApiAccess/Property.kt
new file mode 100644
index 00000000000..c66d3484503
--- /dev/null
+++ b/j2k/tests/testData/ast/kotlinApiAccess/Property.kt
@@ -0,0 +1,8 @@
+import kotlinApi.*
+
+class C() {
+ fun foo(k: KotlinClass) {
+ System.out.println(k.property)
+ k.property = "a"
+ }
+}
\ No newline at end of file