From e131763cb02b6456e7e506645cf6546c886eb7a2 Mon Sep 17 00:00:00 2001 From: Yan Zhulanow Date: Wed, 26 Oct 2016 03:41:13 +0300 Subject: [PATCH] Kapt3: Put static modifiers on nested non-inner classes. Do not initialize synthetic and static fields in constructor. --- .../jetbrains/kotlin/kapt3/JCTreeConverter.kt | 39 ++++++------- .../test/JCTreeConverterTestGenerated.java | 6 ++ .../kapt3/testData/converter/dataClass.txt | 9 +-- .../testData/converter/inheritanceSimple.txt | 8 +-- .../kapt3/testData/converter/nestedClasses.kt | 15 +++++ .../testData/converter/nestedClasses.txt | 57 +++++++++++++++++++ plugins/kapt3/testData/runner/Simple.java | 15 +++++ 7 files changed, 119 insertions(+), 30 deletions(-) create mode 100644 plugins/kapt3/testData/converter/nestedClasses.kt create mode 100644 plugins/kapt3/testData/converter/nestedClasses.txt diff --git a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/JCTreeConverter.kt b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/JCTreeConverter.kt index a35e67f7d83..8a720a05221 100644 --- a/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/JCTreeConverter.kt +++ b/plugins/kapt3/src/org/jetbrains/kotlin/kapt3/JCTreeConverter.kt @@ -46,7 +46,7 @@ class JCTreeConverter( private val MODALITY_MODIFIERS = Opcodes.ACC_FINAL or Opcodes.ACC_ABSTRACT private val CLASS_MODIFIERS = VISIBILITY_MODIFIERS or MODALITY_MODIFIERS or - Opcodes.ACC_DEPRECATED or Opcodes.ACC_INTERFACE or Opcodes.ACC_ANNOTATION or Opcodes.ACC_ENUM + Opcodes.ACC_DEPRECATED or Opcodes.ACC_INTERFACE or Opcodes.ACC_ANNOTATION or Opcodes.ACC_ENUM or Opcodes.ACC_STATIC private val METHOD_MODIFIERS = VISIBILITY_MODIFIERS or MODALITY_MODIFIERS or Opcodes.ACC_SYNCHRONIZED or Opcodes.ACC_STATIC or Opcodes.ACC_NATIVE or Opcodes.ACC_DEPRECATED @@ -80,7 +80,7 @@ class JCTreeConverter( val descriptor = origin.descriptor as? ClassDescriptor ?: return null // Nested classes will be processed during the outer classes conversion - if (descriptor.containingDeclaration is ClassDescriptor) return null + if (descriptor.isNested) return null val classDeclaration = convertClass(clazz) @@ -101,10 +101,13 @@ class JCTreeConverter( if (isSynthetic(clazz.access)) return null val descriptor = origins[clazz]?.descriptor as? ClassDescriptor ?: return null - val modifiers = convertModifiers(clazz.access, ElementKind.CLASS, clazz.visibleAnnotations, clazz.invisibleAnnotations) + val modifiers = convertModifiers( + if (!descriptor.isInner && descriptor.isNested) (clazz.access or Opcodes.ACC_STATIC) else clazz.access, + ElementKind.CLASS, clazz.visibleAnnotations, clazz.invisibleAnnotations) + val simpleName = name(descriptor.name.asString()) val typeParams = JavacList.nil() - val extending = if (clazz.superName == "java/lang/Object") null else convertFqName(clazz.superName) + val extending = if (clazz.superName == "java/lang/Object" || clazz.isEnum()) null else convertFqName(clazz.superName) val implementing = mapValues(clazz.interfaces) { convertFqName(it) } val fields = mapValues(clazz.fields) { convertField(it) } @@ -123,13 +126,14 @@ class JCTreeConverter( val modifiers = convertModifiers(field.access, ElementKind.FIELD, field.visibleAnnotations, field.invisibleAnnotations) val name = name(field.name) - val type = convertFqName(Type.getType(field.desc).className) + val type = Type.getType(field.desc) + val typeExpression = convertFqName(type.className) val value = field.value val initializer = when (value) { is Byte, is Boolean, is Char, is Short, is Int, is Long, is Float, is Double, is String -> treeMaker.Literal(value) - else -> null + else -> if (isFinal(field.access)) convertLiteralExpression(getDefaultValue(type)) else null } - return treeMaker.VarDef(modifiers, name, type, initializer) + return treeMaker.VarDef(modifiers, name, typeExpression, initializer) } private fun convertMethod(method: MethodNode, containingClass: ClassNode, containingClassSimpleName: Name): JCMethodDecl? { @@ -176,7 +180,7 @@ class JCTreeConverter( val superClass = declaration.getSuperClassOrAny() val superClassConstructor = superClass.constructors.firstOrNull { it.visibility.isVisible(null, it, declaration) } - var statements = if (superClassConstructor != null) { + val superClassConstructorCall = if (superClassConstructor != null) { val args = mapValues(superClassConstructor.valueParameters) { param -> convertLiteralExpression(getDefaultValue(typeMapper.mapType(param.type))) } @@ -186,16 +190,7 @@ class JCTreeConverter( JavacList.nil() } - for (field in containingClass.fields) { - if ((field.access and Opcodes.ACC_FINAL) == 0) continue - val type = Type.getType(field.desc) - val assignment = treeMaker.Assign( - convertFqName("this.${field.name}"), - convertLiteralExpression(getDefaultValue(type))) - statements = statements.append(treeMaker.Exec(assignment)) - } - - treeMaker.Block(0, statements) + treeMaker.Block(0, superClassConstructorCall) } else if (returnType == Type.VOID_TYPE) { treeMaker.Block(0, JavacList.nil()) } else { @@ -342,4 +337,10 @@ private operator fun JavacList.plus(other: JavacList): JavacList return this.appendList(other) } -private fun isSynthetic(access: Int) = (access and Opcodes.ACC_SYNTHETIC) > 0 \ No newline at end of file +private val ClassDescriptor.isNested: Boolean + get() = containingDeclaration is ClassDescriptor + +private fun isSynthetic(access: Int) = (access and Opcodes.ACC_SYNTHETIC) > 0 +private fun isFinal(access: Int) = (access and Opcodes.ACC_FINAL) > 0 +private fun isStatic(access: Int) = (access and Opcodes.ACC_STATIC) > 0 +private fun ClassNode.isEnum() = (access and Opcodes.ACC_ENUM) > 0 \ No newline at end of file diff --git a/plugins/kapt3/test/org/jetbrains/kotlin/kapt3/test/JCTreeConverterTestGenerated.java b/plugins/kapt3/test/org/jetbrains/kotlin/kapt3/test/JCTreeConverterTestGenerated.java index c4cb576d3ea..e4031fe64c6 100644 --- a/plugins/kapt3/test/org/jetbrains/kotlin/kapt3/test/JCTreeConverterTestGenerated.java +++ b/plugins/kapt3/test/org/jetbrains/kotlin/kapt3/test/JCTreeConverterTestGenerated.java @@ -46,4 +46,10 @@ public class JCTreeConverterTestGenerated extends AbstractJCTreeConverterTest { String fileName = KotlinTestUtils.navigationMetadata("plugins/kapt3/testData/converter/inheritanceSimple.kt"); doTest(fileName); } + + @TestMetadata("nestedClasses.kt") + public void testNestedClasses() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("plugins/kapt3/testData/converter/nestedClasses.kt"); + doTest(fileName); + } } diff --git a/plugins/kapt3/testData/converter/dataClass.txt b/plugins/kapt3/testData/converter/dataClass.txt index 0a5898081a7..36fb23ce36a 100644 --- a/plugins/kapt3/testData/converter/dataClass.txt +++ b/plugins/kapt3/testData/converter/dataClass.txt @@ -1,8 +1,8 @@ public final class User { - private final java.lang.String firstName; - private final java.lang.String secondName; - private final int age; + private final java.lang.String firstName = null; + private final java.lang.String secondName = null; + private final int age = 0; public final void procedure() { } @@ -21,9 +21,6 @@ public final class User { public /*missing*/ User(java.lang.String firstName, java.lang.String secondName, int age) { super(); - this.firstName = null; - this.secondName = null; - this.age = 0; } public final java.lang.String component1() { diff --git a/plugins/kapt3/testData/converter/inheritanceSimple.txt b/plugins/kapt3/testData/converter/inheritanceSimple.txt index 9c8eb3b095e..7da051873fc 100644 --- a/plugins/kapt3/testData/converter/inheritanceSimple.txt +++ b/plugins/kapt3/testData/converter/inheritanceSimple.txt @@ -11,15 +11,13 @@ public final class Context { //////////////////// -public enum Result extends java.lang.Enum { +public enum Result { ; - public static final Result SUCCESS; - public static final Result ERROR; + public static final Result SUCCESS = null; + public static final Result ERROR = null; protected /*missing*/ Result(java.lang.String $enum_name_or_ordinal$0, int $enum_name_or_ordinal$1) { super(null, 0); - this.SUCCESS = null; - this.ERROR = null; } public static Result[] values() { diff --git a/plugins/kapt3/testData/converter/nestedClasses.kt b/plugins/kapt3/testData/converter/nestedClasses.kt new file mode 100644 index 00000000000..5f6d8b307e2 --- /dev/null +++ b/plugins/kapt3/testData/converter/nestedClasses.kt @@ -0,0 +1,15 @@ +class Test { + class Nested { + class NestedNested + } + + inner class Inner + + object NestedObject + + interface NestedInterface + + enum class NestedEnum { + BLACK, WHITE + } +} \ No newline at end of file diff --git a/plugins/kapt3/testData/converter/nestedClasses.txt b/plugins/kapt3/testData/converter/nestedClasses.txt new file mode 100644 index 00000000000..1e4beaf4dc9 --- /dev/null +++ b/plugins/kapt3/testData/converter/nestedClasses.txt @@ -0,0 +1,57 @@ + +public final class Test { + + public /*missing*/ Test() { + super(); + } + + public static final class Nested { + + public /*missing*/ Nested() { + super(); + } + + public static final class NestedNested { + + public /*missing*/ NestedNested() { + super(); + } + } + } + + public final class Inner { + + public /*missing*/ Inner(Test $outer) { + super(); + } + } + + public static final class NestedObject { + public static final Test.NestedObject INSTANCE = null; + + private /*missing*/ NestedObject() { + super(); + } + } + + public static abstract interface NestedInterface { + } + + public static enum NestedEnum { +; + public static final Test.NestedEnum BLACK = null; + public static final Test.NestedEnum WHITE = null; + + protected /*missing*/ NestedEnum(java.lang.String $enum_name_or_ordinal$0, int $enum_name_or_ordinal$1) { + super(null, 0); + } + + public static Test.NestedEnum[] values() { + return null; + } + + public static Test.NestedEnum valueOf(java.lang.String p0) { + return null; + } + } +} \ No newline at end of file diff --git a/plugins/kapt3/testData/runner/Simple.java b/plugins/kapt3/testData/runner/Simple.java index f2807ab9651..c84f0363859 100644 --- a/plugins/kapt3/testData/runner/Simple.java +++ b/plugins/kapt3/testData/runner/Simple.java @@ -9,4 +9,19 @@ class Simple { @interface MyAnnotation { +} + +enum EnumClass { + BLACK, WHITE +} + + +enum EnumClass2 { + WHITE("A"), RED("B"); + + private final String blah; + + EnumClass2(String blah) { + this.blah = blah; + } } \ No newline at end of file