KT-11990 J2K native to external conversion (#957)

This commit is contained in:
Simon Ogorodnik
2016-09-22 18:09:26 +03:00
committed by Dmitry Jemerov
parent 293d3b4320
commit ab2b6743df
7 changed files with 61 additions and 15 deletions
+21 -12
View File
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.j2k
import com.intellij.openapi.project.Project
import com.intellij.psi.*
import com.intellij.psi.CommonClassNames.*
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.util.InheritanceUtil
import com.intellij.psi.util.PsiMethodUtil
import com.intellij.psi.util.PsiTreeUtil
@@ -352,7 +351,10 @@ class Converter private constructor(
if (propertyInfo.needExplicitGetter) {
if (getMethod != null) {
val method = convertMethod(getMethod, null, null, null, classKind)!!
getter = PropertyAccessor(AccessorKind.GETTER, method.annotations, Modifiers.Empty, method.parameterList, method.body)
if (method.modifiers.contains(Modifier.EXTERNAL))
getter = PropertyAccessor(AccessorKind.GETTER, method.annotations, Modifiers(listOf(Modifier.EXTERNAL)).assignNoPrototype(), null, null)
else
getter = PropertyAccessor(AccessorKind.GETTER, method.annotations, Modifiers.Empty, method.parameterList, method.body)
getter.assignPrototype(getMethod, CommentsAndSpacesInheritance.NO_SPACES)
}
else if (propertyInfo.modifiers.contains(Modifier.OVERRIDE) && !(propertyInfo.superInfo?.isAbstract() ?: false)) {
@@ -374,18 +376,22 @@ class Converter private constructor(
if (propertyInfo.needExplicitSetter) {
val accessorModifiers = Modifiers(propertyInfo.specialSetterAccess.singletonOrEmptyList()).assignNoPrototype()
if (setMethod != null && !propertyInfo.isSetMethodBodyFieldAccess) {
val method = setMethod.let { convertMethod(it, null, null, null, classKind)!! }
val convertedParameter = method.parameterList!!.parameters.single() as FunctionParameter
val parameterAnnotations = convertedParameter.annotations
val parameterList = if (method.body != null || !parameterAnnotations.isEmpty) {
val parameter = FunctionParameter(convertedParameter.identifier, null, FunctionParameter.VarValModifier.None, parameterAnnotations, Modifiers.Empty)
.assignPrototypesFrom(convertedParameter, CommentsAndSpacesInheritance.NO_SPACES)
ParameterList.withNoPrototype(listOf(parameter))
}
val method = convertMethod(setMethod, null, null, null, classKind)!!
if (method.modifiers.contains(Modifier.EXTERNAL))
setter = PropertyAccessor(AccessorKind.SETTER, method.annotations, accessorModifiers.with(Modifier.EXTERNAL), null, null)
else {
null
val convertedParameter = method.parameterList!!.parameters.single() as FunctionParameter
val parameterAnnotations = convertedParameter.annotations
val parameterList = if (method.body != null || !parameterAnnotations.isEmpty) {
val parameter = FunctionParameter(convertedParameter.identifier, null, FunctionParameter.VarValModifier.None, parameterAnnotations, Modifiers.Empty)
.assignPrototypesFrom(convertedParameter, CommentsAndSpacesInheritance.NO_SPACES)
ParameterList.withNoPrototype(listOf(parameter))
}
else {
null
}
setter = PropertyAccessor(AccessorKind.SETTER, method.annotations, accessorModifiers, parameterList, method.body)
}
setter = PropertyAccessor(AccessorKind.SETTER, method.annotations, accessorModifiers, parameterList, method.body)
setter.assignPrototype(setMethod, CommentsAndSpacesInheritance.NO_SPACES)
}
else if (propertyInfo.modifiers.contains(Modifier.OVERRIDE) && !(propertyInfo.superInfo?.isAbstract() ?: false)) {
@@ -726,6 +732,9 @@ class Converter private constructor(
modifiers = modifiers.with(Modifier.OPEN)
}
if (owner.hasModifierProperty(PsiModifier.NATIVE))
modifiers = modifiers.with(Modifier.EXTERNAL)
modifiers = modifiers.adaptForContainingClassVisibility(owner.containingClass).adaptProtectedVisibility(owner)
}
else if (owner is PsiField) {
@@ -27,6 +27,7 @@ enum class Modifier(private val str: String) {
ABSTRACT("abstract"),
OPEN("open"),
OVERRIDE("override"),
EXTERNAL("external"),
INNER("inner");
fun toKotlin(): String = str
@@ -60,7 +60,12 @@ class PropertyInfo(
//TODO: what if annotations are not empty?
val needExplicitGetter: Boolean
get() {
if (getMethod != null && getMethod.body != null && !isGetMethodBodyFieldAccess) return true
if (getMethod != null) {
if (getMethod.hasModifierProperty(PsiModifier.NATIVE))
return true
if (getMethod.body != null && !isGetMethodBodyFieldAccess)
return true
}
return modifiers.contains(Modifier.OVERRIDE) && this.field == null && !modifiers.contains(Modifier.ABSTRACT)
}
@@ -69,8 +74,13 @@ class PropertyInfo(
get() {
if (!isVar) return false
if (specialSetterAccess != null) return true
if (setMethod != null && setMethod.body != null && !isSetMethodBodyFieldAccess) return true
return modifiers.contains(Modifier.OVERRIDE) && this.field == null && !modifiers.contains(Modifier.ABSTRACT)
if (setMethod != null) {
if (setMethod.hasModifierProperty(PsiModifier.NATIVE))
return true
if (setMethod.body != null && !isSetMethodBodyFieldAccess)
return true
}
return modifiers.contains(Modifier.EXTERNAL) || modifiers.contains(Modifier.OVERRIDE) && this.field == null && !modifiers.contains(Modifier.ABSTRACT)
}
companion object {
@@ -0,0 +1,6 @@
public class Foo {
private native final void nativeMethod();
public native final int getBar();
public native final void setBar(int bar);
}
+8
View File
@@ -0,0 +1,8 @@
// ERROR: Property must be initialized or be abstract
class Foo {
private external fun nativeMethod()
var bar: Int
external get
external set
}
@@ -2449,6 +2449,12 @@ public class JavaToKotlinConverterForWebDemoTestGenerated extends AbstractJavaTo
doTest(fileName);
}
@TestMetadata("nativeMethods.java")
public void testNativeMethods() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/function/nativeMethods.java");
doTest(fileName);
}
@TestMetadata("open.java")
public void testOpen() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/function/open.java");
@@ -2449,6 +2449,12 @@ public class JavaToKotlinConverterSingleFileTestGenerated extends AbstractJavaTo
doTest(fileName);
}
@TestMetadata("nativeMethods.java")
public void testNativeMethods() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/function/nativeMethods.java");
doTest(fileName);
}
@TestMetadata("open.java")
public void testOpen() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/function/open.java");