Kapt3: Fix a number of errors in ClassFileToSourceStubConverter:

1. Support strictfp modifier for methods.
2. Support Kotlin top-level methods and properties.
3. Fix visibility modifiers on enum methods.
This commit is contained in:
Yan Zhulanow
2016-11-01 21:59:13 +03:00
committed by Yan Zhulanow
parent e22ce14c36
commit 1f1491f1ca
17 changed files with 487 additions and 13 deletions
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.kapt3.*
import org.jetbrains.kotlin.kapt3.javac.KaptTreeMaker
import org.jetbrains.kotlin.kapt3.javac.KaptJavaFileObject
@@ -48,7 +49,7 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContext, val typeMappe
(Opcodes.ACC_DEPRECATED or Opcodes.ACC_INTERFACE or Opcodes.ACC_ANNOTATION or Opcodes.ACC_ENUM or Opcodes.ACC_STATIC).toLong()
private val METHOD_MODIFIERS = VISIBILITY_MODIFIERS or MODALITY_MODIFIERS or
(Opcodes.ACC_DEPRECATED or Opcodes.ACC_SYNCHRONIZED or Opcodes.ACC_NATIVE or Opcodes.ACC_STATIC).toLong()
(Opcodes.ACC_DEPRECATED or Opcodes.ACC_SYNCHRONIZED or Opcodes.ACC_NATIVE or Opcodes.ACC_STATIC or Opcodes.ACC_STRICT).toLong()
private val FIELD_MODIFIERS = VISIBILITY_MODIFIERS or MODALITY_MODIFIERS or
(Opcodes.ACC_VOLATILE or Opcodes.ACC_TRANSIENT or Opcodes.ACC_ENUM or Opcodes.ACC_STATIC).toLong()
@@ -78,12 +79,11 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContext, val typeMappe
private fun convertTopLevelClass(clazz: ClassNode): JCCompilationUnit? {
val origin = kaptContext.origins[clazz] ?: return null
// ?
val ktFile = origin.element?.containingFile as? KtFile ?: return null
val descriptor = origin.descriptor as? ClassDescriptor ?: return null
val descriptor = origin.descriptor as? DeclarationDescriptor ?: return null
// Nested classes will be processed during the outer classes conversion
if (descriptor.isNested) return null
if ((descriptor as? ClassDescriptor)?.isNested ?: false) return null
val classDeclaration = convertClass(clazz) ?: return null
@@ -106,9 +106,12 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContext, val typeMappe
private fun convertClass(clazz: ClassNode): JCClassDecl? {
if (isSynthetic(clazz.access)) return null
val descriptor = kaptContext.origins[clazz]?.descriptor as? ClassDescriptor ?: return null
val descriptor = kaptContext.origins[clazz]?.descriptor as? DeclarationDescriptor ?: return null
val isNested = (descriptor as? ClassDescriptor)?.isNested ?: false
val isInner = isNested && (descriptor as? ClassDescriptor)?.isInner ?: false
val modifiers = convertModifiers(
if (!descriptor.isInner && descriptor.isNested) (clazz.access or Opcodes.ACC_STATIC) else clazz.access,
if (!isInner && isNested) (clazz.access or Opcodes.ACC_STATIC) else clazz.access,
ElementKind.CLASS, clazz.visibleAnnotations, clazz.invisibleAnnotations)
val isEnum = clazz.isEnum()
@@ -116,6 +119,7 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContext, val typeMappe
val isDefaultImpls = clazz.name.endsWith("${descriptor.name.asString()}/DefaultImpls")
&& isPublic(clazz.access) && isFinal(clazz.access)
&& descriptor is ClassDescriptor
&& descriptor.kind == ClassKind.INTERFACE
// DefaultImpls without any contents don't have INNERCLASS'es inside it (and inside the parent interface)
@@ -195,13 +199,16 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContext, val typeMappe
method.visibleAnnotations
}
val modifiers = convertModifiers(
if (containingClass.isEnum()) (method.access.toLong() and VISIBILITY_MODIFIERS.inv()) else method.access.toLong(),
ElementKind.METHOD, visibleAnnotations, method.invisibleAnnotations)
val isConstructor = method.name == "<init>"
val name = treeMaker.name(method.name)
val modifiers = convertModifiers(
if (containingClass.isEnum() && isConstructor)
(method.access.toLong() and VISIBILITY_MODIFIERS.inv())
else
method.access.toLong(),
ElementKind.METHOD, visibleAnnotations, method.invisibleAnnotations)
val returnType = Type.getReturnType(method.desc)
val jcReturnType = if (isConstructor) null else treeMaker.Type(returnType)
@@ -31,6 +31,12 @@ import java.util.regex.Pattern;
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class ClassFileToSourceStubConverterTestGenerated extends AbstractClassFileToSourceStubConverterTest {
@TestMetadata("abstractMethods.kt")
public void testAbstractMethods() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("plugins/kapt3/testData/converter/abstractMethods.kt");
doTest(fileName);
}
public void testAllFilesPresentInConverter() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("plugins/kapt3/testData/converter"), Pattern.compile("^(.+)\\.kt$"), true);
}
@@ -41,6 +47,12 @@ public class ClassFileToSourceStubConverterTestGenerated extends AbstractClassFi
doTest(fileName);
}
@TestMetadata("annotations2.kt")
public void testAnnotations2() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("plugins/kapt3/testData/converter/annotations2.kt");
doTest(fileName);
}
@TestMetadata("dataClass.kt")
public void testDataClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("plugins/kapt3/testData/converter/dataClass.kt");
@@ -65,6 +77,12 @@ public class ClassFileToSourceStubConverterTestGenerated extends AbstractClassFi
doTest(fileName);
}
@TestMetadata("genericRawSignatures.kt")
public void testGenericRawSignatures() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("plugins/kapt3/testData/converter/genericRawSignatures.kt");
doTest(fileName);
}
@TestMetadata("genericSimple.kt")
public void testGenericSimple() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("plugins/kapt3/testData/converter/genericSimple.kt");
@@ -83,9 +101,33 @@ public class ClassFileToSourceStubConverterTestGenerated extends AbstractClassFi
doTest(fileName);
}
@TestMetadata("jvmStaticFieldInParent.kt")
public void testJvmStaticFieldInParent() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("plugins/kapt3/testData/converter/jvmStaticFieldInParent.kt");
doTest(fileName);
}
@TestMetadata("modifiers.kt")
public void testModifiers() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("plugins/kapt3/testData/converter/modifiers.kt");
doTest(fileName);
}
@TestMetadata("nestedClasses.kt")
public void testNestedClasses() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("plugins/kapt3/testData/converter/nestedClasses.kt");
doTest(fileName);
}
@TestMetadata("strangeNames.kt")
public void testStrangeNames() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("plugins/kapt3/testData/converter/strangeNames.kt");
doTest(fileName);
}
@TestMetadata("topLevel.kt")
public void testTopLevel() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("plugins/kapt3/testData/converter/topLevel.kt");
doTest(fileName);
}
}
+9
View File
@@ -0,0 +1,9 @@
abstract class Base {
protected abstract fun doJob(job: String, delay: Int)
protected abstract fun <T : CharSequence> doJobGeneric(job: T, delay: Int)
}
class Impl : Base() {
override fun doJob(job: String, delay: Int) {}
override fun <T : CharSequence> doJobGeneric(job: T, delay: Int) {}
}
+28
View File
@@ -0,0 +1,28 @@
public abstract class Base {
protected abstract void doJob(java.lang.String job, int delay);
protected abstract <T extends java.lang.CharSequence>void doJobGeneric(T job, int delay);
public Base() {
super();
}
}
////////////////////
public final class Impl extends Base {
@java.lang.Override()
protected void doJob(java.lang.String job, int delay) {
}
@java.lang.Override()
protected <T extends java.lang.CharSequence>void doJobGeneric(T job, int delay) {
}
public Impl() {
super();
}
}
+33
View File
@@ -0,0 +1,33 @@
@file:kotlin.jvm.JvmName("AnnotationsTest")
package test
@Anno("anno-class")
annotation class Anno @Anno("anno-constructor") constructor(
@Anno("anno-value") val value: String,
val anno: Anno = Anno("anno-default")
)
@Anno("clazz")
abstract class Test @Anno("test-constructor") protected constructor(@param:Anno("v-param")
@setparam:Anno("v-setparam")
@property:Anno("v-property")
@get:Anno("v-get")
@set:Anno("v-set") var v: String) {
@Anno("abstract-method")
abstract fun abstractMethod(): String
@Anno("abstract-val")
abstract val abstractVal: String
}
@Anno("top-level-fun")
fun @receiver:Anno("top-level-fun-receiver") String.topLevelFun() {}
@Anno("top-level-val")
val @receiver:Anno("top-level-val-receiver") Int.topLevelVal: String
get() = ""
@Anno("enum")
enum class Enum @Anno("enum-constructor") constructor(@Anno("x") val x: Int) {
@Anno("white") WHITE(1), @Anno("black") BLACK(2)
}
+3
View File
@@ -7,4 +7,7 @@ annotation class Anno1(val value: String)
enum class Enum2(@Anno1("first") val col: String, @Anno1("second") val col2: Int) {
RED("red", 1), WHITE("white", 2);
fun color() = col
private fun privateEnumFun() {}
public fun publicEnumFun() {}
}
+9 -3
View File
@@ -23,15 +23,21 @@ public enum Enum2 {
private final java.lang.String col = null;
private final int col2 = 0;
final java.lang.String color() {
public final java.lang.String color() {
return null;
}
final java.lang.String getCol() {
private final void privateEnumFun() {
}
public final void publicEnumFun() {
}
public final java.lang.String getCol() {
return null;
}
final int getCol2() {
public final int getCol2() {
return 0;
}
@@ -0,0 +1,4 @@
class GenericRawSignatures {
fun <T> genericFun(): T? = null
fun nonGenericFun(): String? = null
}
@@ -0,0 +1,14 @@
public final class GenericRawSignatures {
public final <T extends java.lang.Object>T genericFun() {
return null;
}
public final java.lang.String nonGenericFun() {
return null;
}
public GenericRawSignatures() {
super();
}
}
@@ -0,0 +1,6 @@
class Test {
companion object A {
@JvmStatic
val test: String = ""
}
}
@@ -0,0 +1,23 @@
public final class Test {
private static final java.lang.String test = "";
public static final Test.A A = null;
public Test() {
super();
}
public static final java.lang.String getTest() {
return null;
}
public static final class A {
public final java.lang.String getTest() {
return null;
}
private A() {
super();
}
}
}
+37
View File
@@ -0,0 +1,37 @@
package modifiers
public class PublicClass public constructor()
public open class PublicClassProtectedConstructor protected constructor() {
protected interface ProtectedInterface
private interface PrivateInterface
}
public abstract class PublicClassPrivateConstructor private constructor()
internal class InternalClass
private class PrivateClass
public interface PublicInterface
internal interface InternalInterface
private interface PrivateInterface
sealed class SealedClass {
class One : SealedClass()
open class Two : SealedClass()
abstract class Three : Two()
final class Four : Three()
}
class Modifiers {
@Transient
val transientField: String = ""
@Volatile
var volatileField: String = ""
@Strictfp
fun strictFp() {}
@JvmOverloads
fun overloads(a: String = "", n: Int = 5): String = null!!
}
+157
View File
@@ -0,0 +1,157 @@
package modifiers;
public final class PublicClass {
public PublicClass() {
super();
}
}
////////////////////
package modifiers;
public class PublicClassProtectedConstructor {
protected PublicClassProtectedConstructor() {
super();
}
protected static abstract interface ProtectedInterface {
}
private static abstract interface PrivateInterface {
}
}
////////////////////
package modifiers;
public abstract class PublicClassPrivateConstructor {
private PublicClassPrivateConstructor() {
super();
}
}
////////////////////
package modifiers;
public final class InternalClass {
public InternalClass() {
super();
}
}
////////////////////
package modifiers;
final class PrivateClass {
public PrivateClass() {
super();
}
}
////////////////////
package modifiers;
public abstract interface PublicInterface {
}
////////////////////
package modifiers;
public abstract interface InternalInterface {
}
////////////////////
package modifiers;
abstract interface PrivateInterface {
}
////////////////////
package modifiers;
public abstract class SealedClass {
private SealedClass() {
super();
}
public static final class One extends modifiers.SealedClass {
public One() {
super();
}
}
public static class Two extends modifiers.SealedClass {
public Two() {
super();
}
}
public static abstract class Three extends modifiers.SealedClass.Two {
public Three() {
super();
}
}
public static final class Four extends modifiers.SealedClass.Three {
public Four() {
super();
}
}
}
////////////////////
package modifiers;
public final class Modifiers {
private final transient java.lang.String transientField = "";
private volatile java.lang.String volatileField;
public final java.lang.String getTransientField() {
return null;
}
public final java.lang.String getVolatileField() {
return null;
}
public final void setVolatileField(java.lang.String p0) {
}
public final strictfp void strictFp() {
}
public final java.lang.String overloads(java.lang.String a, int n) {
return null;
}
public final java.lang.String overloads(java.lang.String p0) {
return null;
}
public final java.lang.String overloads() {
return null;
}
public Modifiers() {
super();
}
}
+12
View File
@@ -0,0 +1,12 @@
class `My $ name` {
fun `(^_^)`(`)))))`: Int) {}
// unicode symbol •
val `(@•@)`: String = ""
// russian
val `Котлин-компилятор`: String = ""
// japanese hiragana
fun `こ と り ん!`() {}
}
+22
View File
@@ -0,0 +1,22 @@
public final class My $ name {
private final java.lang.String (@\u2022@) = "";
private final java.lang.String \u041a\u043e\u0442\u043b\u0438\u043d-\u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 = "";
public final void (^_^)(int )))))) {
}
public final java.lang.String get(@\u2022@)() {
return null;
}
public final java.lang.String get\u041a\u043e\u0442\u043b\u0438\u043d-\u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440() {
return null;
}
public final void \u3053\u3000\u3068\u3000\u308a\u3000\u3093\uff01() {
}
public My $ name() {
super();
}
}
+21
View File
@@ -0,0 +1,21 @@
package test.another
annotation class Anno(val value: String)
fun topLevelFunction(): String? = null
fun <X : CharSequence, T : List<out X>> topLevelGenericFunction(): T? {
return null!!
}
val topLevelProperty = 2
val topLevelProperty2: String
get() = ""
fun @receiver:Anno("rec") String.extensionFunction(@Anno("1") a: String, @Anno("2") b: String) {}
@Anno("extpr")
var <T: Any> @receiver:Anno("propRec") T.extensionProperty: String
get() = ""
set(@Anno("setparam") setParamName) {}
+50
View File
@@ -0,0 +1,50 @@
package test.another;
public abstract @interface Anno {
public abstract java.lang.String value();
}
////////////////////
package test.another;
public final class another {
public another() {
super();
}
private static final int topLevelProperty = 2;
public static final java.lang.String topLevelFunction() {
return null;
}
public static final <X extends java.lang.CharSequence, T extends java.util.List<? extends X>>T topLevelGenericFunction() {
return null;
}
public static final int getTopLevelProperty() {
return 0;
}
public static final java.lang.String getTopLevelProperty2() {
return null;
}
public static final void extensionFunction(@test.another.Anno(value = "rec")
java.lang.String $receiver, @test.another.Anno(value = "1")
java.lang.String a, @test.another.Anno(value = "2")
java.lang.String b) {
}
public static final <T extends java.lang.Object>java.lang.String getExtensionProperty(@test.another.Anno(value = "propRec")
T $receiver) {
return null;
}
public static final <T extends java.lang.Object>void setExtensionProperty(@test.another.Anno(value = "propRec")
T $receiver, @test.another.Anno(value = "setparam")
java.lang.String setParamName) {
}
}