Java to Kotlin converter: access modifiers of factory functions + factory functions for nested classes
This commit is contained in:
@@ -120,7 +120,8 @@ class ConstructorConverter(private val psiClass: PsiClass, private val converter
|
|||||||
typeParameterList.parameters,
|
typeParameterList.parameters,
|
||||||
Nullability.NotNull,
|
Nullability.NotNull,
|
||||||
converter.settings).assignNoPrototype()
|
converter.settings).assignNoPrototype()
|
||||||
return FactoryFunction(constructor.declarationIdentifier(), annotations, modifiers, factoryFunctionType, params, typeParameterList, body)
|
return FactoryFunction(constructor.declarationIdentifier(), annotations, correctFactoryFunctionAccess(modifiers),
|
||||||
|
factoryFunctionType, params, typeParameterList, body)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -344,6 +345,16 @@ class ConstructorConverter(private val psiClass: PsiClass, private val converter
|
|||||||
return statements
|
return statements
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun correctFactoryFunctionAccess(modifiers: Modifiers): Modifiers {
|
||||||
|
val classAccess = converter.convertModifiers(psiClass).accessModifier()
|
||||||
|
return when(modifiers.accessModifier()) {
|
||||||
|
Modifier.PUBLIC -> modifiers.without(Modifier.PUBLIC).with(classAccess)
|
||||||
|
Modifier.PROTECTED -> modifiers.without(Modifier.PROTECTED).with(classAccess)
|
||||||
|
Modifier.PRIVATE -> modifiers
|
||||||
|
else/*internal*/ -> if (classAccess != Modifier.PUBLIC) modifiers.with(classAccess) else modifiers
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun PsiMethodCallExpression.isSuperConstructorCall(): Boolean {
|
private fun PsiMethodCallExpression.isSuperConstructorCall(): Boolean {
|
||||||
val ref = getMethodExpression()
|
val ref = getMethodExpression()
|
||||||
return ref.getCanonicalText() == "super" && ref.resolve()?.isConstructor() ?: false
|
return ref.getCanonicalText() == "super" && ref.resolve()?.isConstructor() ?: false
|
||||||
|
|||||||
@@ -138,7 +138,10 @@ public class Converter private(val project: Project, val settings: ConverterSett
|
|||||||
else if (member is FactoryFunction) {
|
else if (member is FactoryFunction) {
|
||||||
factoryFunctions.add(member)
|
factoryFunctions.add(member)
|
||||||
}
|
}
|
||||||
else if (useClassObject && psiMember !is PsiClass && psiMember.hasModifierProperty(PsiModifier.STATIC)) {
|
else if (useClassObject &&
|
||||||
|
psiMember.hasModifierProperty(PsiModifier.STATIC) &&
|
||||||
|
// we generate nested classes with factory functions into class object as a workaround until secondary constructors supported by Kotlin
|
||||||
|
(psiMember !is PsiClass || (member as Class).body.factoryFunctions.isNotEmpty())) {
|
||||||
classObjectMembers.add(member)
|
classObjectMembers.add(member)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -154,6 +157,10 @@ public class Converter private(val project: Project, val settings: ConverterSett
|
|||||||
// do not convert private static methods into class object if possible
|
// do not convert private static methods into class object if possible
|
||||||
private fun shouldGenerateClassObject(psiClass: PsiClass, convertedMembers: Map<PsiMember, Member>): Boolean {
|
private fun shouldGenerateClassObject(psiClass: PsiClass, convertedMembers: Map<PsiMember, Member>): Boolean {
|
||||||
if (psiClass.isEnum()) return false
|
if (psiClass.isEnum()) return false
|
||||||
|
|
||||||
|
// we generate nested classes with factory functions into class object as a workaround until secondary constructors supported by Kotlin
|
||||||
|
if (convertedMembers.values().any { it is Class && !it.modifiers.contains(Modifier.INNER) && it.body.factoryFunctions.isNotEmpty() }) return true
|
||||||
|
|
||||||
val members = convertedMembers.keySet().filter { !it.isConstructor() }
|
val members = convertedMembers.keySet().filter { !it.isConstructor() }
|
||||||
val classObjectMembers = members.filter { it !is PsiClass && it.hasModifierProperty(PsiModifier.STATIC) }
|
val classObjectMembers = members.filter { it !is PsiClass && it.hasModifierProperty(PsiModifier.STATIC) }
|
||||||
val nestedClasses = members.filterIsInstance(javaClass<PsiClass>()).filter { it.hasModifierProperty(PsiModifier.STATIC) }
|
val nestedClasses = members.filterIsInstance(javaClass<PsiClass>()).filter { it.hasModifierProperty(PsiModifier.STATIC) }
|
||||||
|
|||||||
@@ -33,10 +33,6 @@ enum class Modifier(val name: String) {
|
|||||||
|
|
||||||
val ACCESS_MODIFIERS = setOf(Modifier.PUBLIC, Modifier.PROTECTED, Modifier.PRIVATE)
|
val ACCESS_MODIFIERS = setOf(Modifier.PUBLIC, Modifier.PROTECTED, Modifier.PRIVATE)
|
||||||
|
|
||||||
fun Collection<Modifier>.accessModifier(): Modifier? {
|
|
||||||
return firstOrNull { it in ACCESS_MODIFIERS }
|
|
||||||
}
|
|
||||||
|
|
||||||
class Modifiers(val modifiers: Collection<Modifier>) : Element() {
|
class Modifiers(val modifiers: Collection<Modifier>) : Element() {
|
||||||
override fun generateCode(builder: CodeBuilder) {
|
override fun generateCode(builder: CodeBuilder) {
|
||||||
builder.append(modifiers.sortBy { it.ordinal() }.map { it.toKotlin() }.joinToString(" "))
|
builder.append(modifiers.sortBy { it.ordinal() }.map { it.toKotlin() }.joinToString(" "))
|
||||||
@@ -45,7 +41,7 @@ class Modifiers(val modifiers: Collection<Modifier>) : Element() {
|
|||||||
override val isEmpty: Boolean
|
override val isEmpty: Boolean
|
||||||
get() = modifiers.isEmpty()
|
get() = modifiers.isEmpty()
|
||||||
|
|
||||||
fun with(modifier: Modifier): Modifiers = Modifiers(modifiers + listOf(modifier)).assignPrototypesFrom(this)
|
fun with(modifier: Modifier?): Modifiers = if (modifier != null) Modifiers(modifiers + listOf(modifier)).assignPrototypesFrom(this) else this
|
||||||
|
|
||||||
fun without(modifier: Modifier): Modifiers {
|
fun without(modifier: Modifier): Modifiers {
|
||||||
val set = HashSet(modifiers)
|
val set = HashSet(modifiers)
|
||||||
@@ -58,7 +54,9 @@ class Modifiers(val modifiers: Collection<Modifier>) : Element() {
|
|||||||
val isPublic: Boolean get() = contains(Modifier.PUBLIC)
|
val isPublic: Boolean get() = contains(Modifier.PUBLIC)
|
||||||
val isPrivate: Boolean get() = contains(Modifier.PRIVATE)
|
val isPrivate: Boolean get() = contains(Modifier.PRIVATE)
|
||||||
val isProtected: Boolean get() = contains(Modifier.PROTECTED)
|
val isProtected: Boolean get() = contains(Modifier.PROTECTED)
|
||||||
val isInternal: Boolean get() = !isPublic && !isPrivate && !isProtected
|
val isInternal: Boolean get() = accessModifier() == null
|
||||||
|
|
||||||
|
fun accessModifier(): Modifier? = modifiers.firstOrNull { it in ACCESS_MODIFIERS }
|
||||||
|
|
||||||
class object {
|
class object {
|
||||||
val Empty = Modifiers(listOf())
|
val Empty = Modifiers(listOf())
|
||||||
|
|||||||
@@ -16,17 +16,14 @@
|
|||||||
|
|
||||||
package org.jetbrains.jet.j2k.test;
|
package org.jetbrains.jet.j2k.test;
|
||||||
|
|
||||||
import junit.framework.Assert;
|
|
||||||
import junit.framework.Test;
|
import junit.framework.Test;
|
||||||
import junit.framework.TestSuite;
|
import junit.framework.TestSuite;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
import org.jetbrains.jet.JetTestUtils;
|
import org.jetbrains.jet.JetTestUtils;
|
||||||
import org.jetbrains.jet.test.InnerTestClasses;
|
import org.jetbrains.jet.test.InnerTestClasses;
|
||||||
import org.jetbrains.jet.test.TestMetadata;
|
import org.jetbrains.jet.test.TestMetadata;
|
||||||
|
|
||||||
import org.jetbrains.jet.j2k.test.AbstractJavaToKotlinConverterTest;
|
import java.io.File;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
/** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
/** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||||
@SuppressWarnings("all")
|
@SuppressWarnings("all")
|
||||||
@@ -891,6 +888,21 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv
|
|||||||
doTest("j2k/tests/testData/ast/constructors/qualifiedRefInFactoryFun.java");
|
doTest("j2k/tests/testData/ast/constructors/qualifiedRefInFactoryFun.java");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("secondaryConstructorsInInnerClass.java")
|
||||||
|
public void testSecondaryConstructorsInInnerClass() throws Exception {
|
||||||
|
doTest("j2k/tests/testData/ast/constructors/secondaryConstructorsInInnerClass.java");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("secondaryConstructorsInNestedClass.java")
|
||||||
|
public void testSecondaryConstructorsInNestedClass() throws Exception {
|
||||||
|
doTest("j2k/tests/testData/ast/constructors/secondaryConstructorsInNestedClass.java");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("secondaryConstructorsVisibility.java")
|
||||||
|
public void testSecondaryConstructorsVisibility() throws Exception {
|
||||||
|
doTest("j2k/tests/testData/ast/constructors/secondaryConstructorsVisibility.java");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("staticFieldRefInFactoryFun.java")
|
@TestMetadata("staticFieldRefInFactoryFun.java")
|
||||||
public void testStaticFieldRefInFactoryFun() throws Exception {
|
public void testStaticFieldRefInFactoryFun() throws Exception {
|
||||||
doTest("j2k/tests/testData/ast/constructors/staticFieldRefInFactoryFun.java");
|
doTest("j2k/tests/testData/ast/constructors/staticFieldRefInFactoryFun.java");
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ private fun C(arg1: Int, arg2: Int): C {
|
|||||||
return C(arg1, arg2, 0)
|
return C(arg1, arg2, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun C(arg1: Int): C {
|
fun C(arg1: Int): C {
|
||||||
return C(arg1, 0, 0)
|
return C(arg1, 0, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,74 @@
|
|||||||
|
//file
|
||||||
|
class Outer {
|
||||||
|
private class Inner1 {
|
||||||
|
public Inner1(){}
|
||||||
|
|
||||||
|
public Inner1(int a) {
|
||||||
|
this();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Inner1(char c) {
|
||||||
|
this();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Inner1(boolean b) {
|
||||||
|
this();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class Inner2 {
|
||||||
|
public Inner2(){}
|
||||||
|
|
||||||
|
public Inner2(int a) {
|
||||||
|
this();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Inner2(char c) {
|
||||||
|
this();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Inner2(boolean b) {
|
||||||
|
this();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class Inner3 {
|
||||||
|
public Inner3(){}
|
||||||
|
|
||||||
|
public Inner3(int a) {
|
||||||
|
this();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Inner3(char c) {
|
||||||
|
this();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Inner3(boolean b) {
|
||||||
|
this();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Inner4 {
|
||||||
|
public Inner4(){}
|
||||||
|
|
||||||
|
public Inner4(int a) {
|
||||||
|
this();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Inner4(char c) {
|
||||||
|
this();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Inner4(boolean b) {
|
||||||
|
this();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void foo() {
|
||||||
|
Inner1 inner1 = new Inner1(1);
|
||||||
|
Inner2 inner2 = new Inner2(2);
|
||||||
|
Inner3 inner3 = new Inner3(3);
|
||||||
|
Inner4 inner4 = new Inner4(4);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
class Outer {
|
||||||
|
|
||||||
|
private fun Inner1(a: Int): Inner1 {
|
||||||
|
return Inner1()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Inner1(c: Char): Inner1 {
|
||||||
|
return Inner1()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Inner1(b: Boolean): Inner1 {
|
||||||
|
return Inner1()
|
||||||
|
}
|
||||||
|
|
||||||
|
private inner class Inner1
|
||||||
|
|
||||||
|
|
||||||
|
protected fun Inner2(a: Int): Inner2 {
|
||||||
|
return Inner2()
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun Inner2(c: Char): Inner2 {
|
||||||
|
return Inner2()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Inner2(b: Boolean): Inner2 {
|
||||||
|
return Inner2()
|
||||||
|
}
|
||||||
|
|
||||||
|
protected inner class Inner2
|
||||||
|
|
||||||
|
|
||||||
|
fun Inner3(a: Int): Inner3 {
|
||||||
|
return Inner3()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Inner3(c: Char): Inner3 {
|
||||||
|
return Inner3()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Inner3(b: Boolean): Inner3 {
|
||||||
|
return Inner3()
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class Inner3
|
||||||
|
|
||||||
|
|
||||||
|
public fun Inner4(a: Int): Inner4 {
|
||||||
|
return Inner4()
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun Inner4(c: Char): Inner4 {
|
||||||
|
return Inner4()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Inner4(b: Boolean): Inner4 {
|
||||||
|
return Inner4()
|
||||||
|
}
|
||||||
|
|
||||||
|
public inner class Inner4
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
val inner1 = Inner1(1)
|
||||||
|
val inner2 = Inner2(2)
|
||||||
|
val inner3 = Inner3(3)
|
||||||
|
val inner4 = Inner4(4)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
//file
|
||||||
|
class Outer {
|
||||||
|
private static class Nested1 {
|
||||||
|
public Nested1(){}
|
||||||
|
|
||||||
|
public Nested1(int a) {
|
||||||
|
this();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Nested1(char c) {
|
||||||
|
this();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Nested1(boolean b) {
|
||||||
|
this();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static class Nested2 {
|
||||||
|
public Nested2(){}
|
||||||
|
|
||||||
|
public Nested2(int a) {
|
||||||
|
this();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Nested2(char c) {
|
||||||
|
this();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Nested2(boolean b) {
|
||||||
|
this();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Nested3 {
|
||||||
|
public Nested3(){}
|
||||||
|
|
||||||
|
public Nested3(int a) {
|
||||||
|
this();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Nested3(char c) {
|
||||||
|
this();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Nested3(boolean b) {
|
||||||
|
this();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Nested4 {
|
||||||
|
public Nested4(){}
|
||||||
|
|
||||||
|
public Nested4(int a) {
|
||||||
|
this();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Nested4(char c) {
|
||||||
|
this();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Nested4(boolean b) {
|
||||||
|
this();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void foo() {
|
||||||
|
Nested1 nested1 = new Nested1(1);
|
||||||
|
Nested2 nested2 = new Nested2(2);
|
||||||
|
Nested3 nested3 = new Nested3(3);
|
||||||
|
Nested4 nested4 = new Nested4(4);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
class Outer {
|
||||||
|
class object {
|
||||||
|
|
||||||
|
private fun Nested1(a: Int): Nested1 {
|
||||||
|
return Nested1()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Nested1(c: Char): Nested1 {
|
||||||
|
return Nested1()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Nested1(b: Boolean): Nested1 {
|
||||||
|
return Nested1()
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Nested1
|
||||||
|
|
||||||
|
|
||||||
|
protected fun Nested2(a: Int): Nested2 {
|
||||||
|
return Nested2()
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun Nested2(c: Char): Nested2 {
|
||||||
|
return Nested2()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Nested2(b: Boolean): Nested2 {
|
||||||
|
return Nested2()
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class Nested2
|
||||||
|
|
||||||
|
|
||||||
|
fun Nested3(a: Int): Nested3 {
|
||||||
|
return Nested3()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Nested3(c: Char): Nested3 {
|
||||||
|
return Nested3()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Nested3(b: Boolean): Nested3 {
|
||||||
|
return Nested3()
|
||||||
|
}
|
||||||
|
|
||||||
|
class Nested3
|
||||||
|
|
||||||
|
|
||||||
|
public fun Nested4(a: Int): Nested4 {
|
||||||
|
return Nested4()
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun Nested4(c: Char): Nested4 {
|
||||||
|
return Nested4()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Nested4(b: Boolean): Nested4 {
|
||||||
|
return Nested4()
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Nested4
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
val nested1 = Nested1(1)
|
||||||
|
val nested2 = Nested2(2)
|
||||||
|
val nested3 = Nested3(3)
|
||||||
|
val nested4 = Nested4(4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
//file
|
||||||
|
class A {
|
||||||
|
public A() {}
|
||||||
|
|
||||||
|
public A(int a) { this(); }
|
||||||
|
|
||||||
|
protected A(char c) { this(); }
|
||||||
|
|
||||||
|
A(float f) { this(); }
|
||||||
|
|
||||||
|
private A(double d) { this(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class B {
|
||||||
|
public B() {}
|
||||||
|
|
||||||
|
public B(int a) { this(); }
|
||||||
|
|
||||||
|
protected B(char c) { this(); }
|
||||||
|
|
||||||
|
B(float f) { this(); }
|
||||||
|
|
||||||
|
private B(double d) { this(); }
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
fun A(a: Int): A {
|
||||||
|
return A()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun A(c: Char): A {
|
||||||
|
return A()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun A(f: Float): A {
|
||||||
|
return A()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun A(d: Double): A {
|
||||||
|
return A()
|
||||||
|
}
|
||||||
|
|
||||||
|
class A
|
||||||
|
|
||||||
|
|
||||||
|
public fun B(a: Int): B {
|
||||||
|
return B()
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun B(c: Char): B {
|
||||||
|
return B()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun B(f: Float): B {
|
||||||
|
return B()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun B(d: Double): B {
|
||||||
|
return B()
|
||||||
|
}
|
||||||
|
|
||||||
|
public class B
|
||||||
Reference in New Issue
Block a user