Kapt3: Call super class constructor with some default parameters.

Allow interface, annotation, enum modifiers on class.
This commit is contained in:
Yan Zhulanow
2016-10-26 01:50:53 +03:00
committed by Yan Zhulanow
parent edaadb0d48
commit 10cfde4ab9
6 changed files with 114 additions and 8 deletions
@@ -58,6 +58,10 @@ public class ClassFileFactory implements OutputFileCollection {
this.builderFactory = builderFactory;
}
public GenerationState getGenerationState() {
return state;
}
@NotNull
public ClassBuilder newVisitor(
@NotNull JvmDeclarationOrigin origin,
@@ -23,8 +23,10 @@ import com.sun.tools.javac.util.Context
import com.sun.tools.javac.util.Name
import com.sun.tools.javac.util.Names
import com.sun.tools.javac.util.SharedNameTable
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
@@ -32,12 +34,18 @@ import org.jetbrains.org.objectweb.asm.tree.*
import javax.lang.model.element.ElementKind
import com.sun.tools.javac.util.List as JavacList
class JCTreeConverter(context: Context, val classes: List<ClassNode>, val origins: Map<Any, JvmDeclarationOrigin>) {
class JCTreeConverter(
context: Context,
val typeMapper: KotlinTypeMapper,
val classes: List<ClassNode>,
val origins: Map<Any, JvmDeclarationOrigin>
) {
private companion object {
private val VISIBILITY_MODIFIERS = Opcodes.ACC_PUBLIC or Opcodes.ACC_PRIVATE or Opcodes.ACC_PROTECTED
private val MODALITY_MODIFIERS = Opcodes.ACC_FINAL or Opcodes.ACC_ABSTRACT
private val CLASS_MODIFIERS = VISIBILITY_MODIFIERS or MODALITY_MODIFIERS or Opcodes.ACC_DEPRECATED
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
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
@@ -72,7 +80,7 @@ class JCTreeConverter(context: Context, val classes: List<ClassNode>, val origin
// Nested classes will be processed during the outer classes conversion
if (descriptor.containingDeclaration is ClassDescriptor) return null
val classDeclaration = convert(clazz)
val classDeclaration = convertClass(clazz)
val packageAnnotations = JavacList.nil<JCAnnotation>()
val packageName = ktFile.packageFqName.asString()
@@ -87,7 +95,7 @@ class JCTreeConverter(context: Context, val classes: List<ClassNode>, val origin
/**
* Returns false for the inner classe or if the origin for the class was not found.
*/
private fun convert(clazz: ClassNode): JCClassDecl? {
private fun convertClass(clazz: ClassNode): JCClassDecl? {
if (isSynthetic(clazz.access)) return null
val descriptor = origins[clazz]?.descriptor as? ClassDescriptor ?: return null
@@ -102,7 +110,7 @@ class JCTreeConverter(context: Context, val classes: List<ClassNode>, val origin
val nestedClasses = mapValues<InnerClassNode, JCTree>(clazz.innerClasses) { innerClass ->
if (innerClass.outerName != clazz.name) return@mapValues null
val innerClassNode = classes.firstOrNull { it.name == innerClass.name } ?: return@mapValues null
convert(innerClassNode)
convertClass(innerClassNode)
}
return treeMaker.ClassDef(modifiers, simpleName, typeParams, extending, implementing, fields + methods + nestedClasses)
@@ -150,7 +158,20 @@ class JCTreeConverter(context: Context, val classes: List<ClassNode>, val origin
val body = if (defaultValue != null) {
null
} else if (isConstructor) {
var statements = JavacList.nil<JCStatement>()
// We already checked it in convertClass()
val declaration = origins[containingClass]?.descriptor as ClassDescriptor
val superClass = declaration.getSuperClassOrAny()
val superClassConstructor = superClass.constructors.firstOrNull { it.visibility.isVisible(null, it, declaration) }
var statements = if (superClassConstructor != null) {
val args = mapValues(superClassConstructor.valueParameters) { param ->
convertLiteralExpression(getDefaultValue(typeMapper.mapType(param.type)))
}
val call = treeMaker.Apply(JavacList.nil(), convertSimpleName("super"), args)
JavacList.of<JCStatement>(treeMaker.Exec(call))
} else {
JavacList.nil<JCStatement>()
}
for (field in containingClass.fields) {
if ((field.access and Opcodes.ACC_FINAL) == 0) continue
@@ -34,10 +34,11 @@ abstract class AbstractJCTreeConverterTest : CodegenTestCase() {
val txtFile = File(wholeFile.parentFile, wholeFile.nameWithoutExtension + ".txt")
val classBuilderFactory = Kapt3BuilderFactory()
CodegenTestUtil.generateFiles(myEnvironment, myFiles, classBuilderFactory)
val factory = CodegenTestUtil.generateFiles(myEnvironment, myFiles, classBuilderFactory)
val typeMapper = factory.generationState.typeMapper
val kaptRunner = KaptRunner()
val converter = JCTreeConverter(kaptRunner.context, classBuilderFactory.compiledClasses, classBuilderFactory.origins)
val converter = JCTreeConverter(kaptRunner.context, typeMapper, classBuilderFactory.compiledClasses, classBuilderFactory.origins)
val javaFiles = converter.convert()
KotlinTestUtils.assertEqualsToFile(txtFile, javaFiles.joinToString("\n\n////////////////////\n\n"))
@@ -40,4 +40,10 @@ public class JCTreeConverterTestGenerated extends AbstractJCTreeConverterTest {
String fileName = KotlinTestUtils.navigationMetadata("plugins/kapt3/testData/converter/dataClass.kt");
doTest(fileName);
}
@TestMetadata("inheritanceSimple.kt")
public void testInheritanceSimple() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("plugins/kapt3/testData/converter/inheritanceSimple.kt");
doTest(fileName);
}
}
+13
View File
@@ -0,0 +1,13 @@
interface Context
enum class Result {
SUCCESS, ERROR
}
abstract class BaseClass(context: Context, num: Int, bool: Boolean) {
abstract fun doJob(): Result
}
class Inheritor(context: Context) : BaseClass(context, 5, true) {
override fun doJob() = Result.SUCCESS
}
+61
View File
@@ -0,0 +1,61 @@
public abstract interface Context {
}
////////////////////
public final class Context {
}
////////////////////
public enum Result extends java.lang.Enum {
;
public static final Result SUCCESS;
public static final Result ERROR;
protected /*missing*/ Result(@java.lang.Synthetic()
java.lang.String $enum_name_or_ordinal$0, @java.lang.Synthetic()
int $enum_name_or_ordinal$1) {
super(null, 0);
this.SUCCESS = null;
this.ERROR = null;
}
public static Result[] values() {
return null;
}
public static Result valueOf(java.lang.String p0) {
return null;
}
}
////////////////////
public abstract class BaseClass {
public abstract Result doJob() {
return null;
}
public /*missing*/ BaseClass(Context context, int num, boolean bool) {
super();
}
}
////////////////////
public final class Inheritor extends BaseClass {
public Result doJob() {
return null;
}
public /*missing*/ Inheritor(Context context) {
super(null, 0, false);
}
}