Kapt3: Call super class constructor with some default parameters.
Allow interface, annotation, enum modifiers on class.
This commit is contained in:
committed by
Yan Zhulanow
parent
edaadb0d48
commit
10cfde4ab9
@@ -58,6 +58,10 @@ public class ClassFileFactory implements OutputFileCollection {
|
|||||||
this.builderFactory = builderFactory;
|
this.builderFactory = builderFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public GenerationState getGenerationState() {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public ClassBuilder newVisitor(
|
public ClassBuilder newVisitor(
|
||||||
@NotNull JvmDeclarationOrigin origin,
|
@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.Name
|
||||||
import com.sun.tools.javac.util.Names
|
import com.sun.tools.javac.util.Names
|
||||||
import com.sun.tools.javac.util.SharedNameTable
|
import com.sun.tools.javac.util.SharedNameTable
|
||||||
|
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
|
||||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
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 javax.lang.model.element.ElementKind
|
||||||
import com.sun.tools.javac.util.List as JavacList
|
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 companion object {
|
||||||
private val VISIBILITY_MODIFIERS = Opcodes.ACC_PUBLIC or Opcodes.ACC_PRIVATE or Opcodes.ACC_PROTECTED
|
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 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
|
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
|
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
|
// Nested classes will be processed during the outer classes conversion
|
||||||
if (descriptor.containingDeclaration is ClassDescriptor) return null
|
if (descriptor.containingDeclaration is ClassDescriptor) return null
|
||||||
|
|
||||||
val classDeclaration = convert(clazz)
|
val classDeclaration = convertClass(clazz)
|
||||||
|
|
||||||
val packageAnnotations = JavacList.nil<JCAnnotation>()
|
val packageAnnotations = JavacList.nil<JCAnnotation>()
|
||||||
val packageName = ktFile.packageFqName.asString()
|
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.
|
* 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
|
if (isSynthetic(clazz.access)) return null
|
||||||
|
|
||||||
val descriptor = origins[clazz]?.descriptor as? ClassDescriptor ?: 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 ->
|
val nestedClasses = mapValues<InnerClassNode, JCTree>(clazz.innerClasses) { innerClass ->
|
||||||
if (innerClass.outerName != clazz.name) return@mapValues null
|
if (innerClass.outerName != clazz.name) return@mapValues null
|
||||||
val innerClassNode = classes.firstOrNull { it.name == innerClass.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)
|
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) {
|
val body = if (defaultValue != null) {
|
||||||
null
|
null
|
||||||
} else if (isConstructor) {
|
} 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) {
|
for (field in containingClass.fields) {
|
||||||
if ((field.access and Opcodes.ACC_FINAL) == 0) continue
|
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 txtFile = File(wholeFile.parentFile, wholeFile.nameWithoutExtension + ".txt")
|
||||||
val classBuilderFactory = Kapt3BuilderFactory()
|
val classBuilderFactory = Kapt3BuilderFactory()
|
||||||
CodegenTestUtil.generateFiles(myEnvironment, myFiles, classBuilderFactory)
|
val factory = CodegenTestUtil.generateFiles(myEnvironment, myFiles, classBuilderFactory)
|
||||||
|
val typeMapper = factory.generationState.typeMapper
|
||||||
|
|
||||||
val kaptRunner = KaptRunner()
|
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()
|
val javaFiles = converter.convert()
|
||||||
|
|
||||||
KotlinTestUtils.assertEqualsToFile(txtFile, javaFiles.joinToString("\n\n////////////////////\n\n"))
|
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");
|
String fileName = KotlinTestUtils.navigationMetadata("plugins/kapt3/testData/converter/dataClass.kt");
|
||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inheritanceSimple.kt")
|
||||||
|
public void testInheritanceSimple() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("plugins/kapt3/testData/converter/inheritanceSimple.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user