Kapt3: Number of bugfixes in JCTreeConverter:

Convert Java primitive and array types properly.
Enums: ignore first two synthetic constructor parameters, do not generate super class constructor call, add ACC_ENUM flag to enum values, do not generate "values" and "valueOf" methods.
Provide a JavaFileObject for JCCompilationUnit.
Handle DefaultImpls, ignore empty DefaultImpls classes.
Use a name table from Javac Names.
This commit is contained in:
Yan Zhulanow
2016-10-26 22:07:31 +03:00
committed by Yan Zhulanow
parent e131763cb0
commit e4158a5571
18 changed files with 618 additions and 92 deletions
@@ -16,23 +16,26 @@
package org.jetbrains.kotlin.kapt3
import com.sun.tools.javac.code.TypeTag
import com.sun.tools.javac.file.JavacFileManager
import com.sun.tools.javac.tree.JCTree
import com.sun.tools.javac.tree.JCTree.*
import com.sun.tools.javac.tree.TreeMaker
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.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind
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
import org.jetbrains.org.objectweb.asm.tree.*
import java.util.*
import javax.lang.model.element.ElementKind
import javax.tools.JavaFileManager
import com.sun.tools.javac.util.List as JavacList
class JCTreeConverter(
@@ -52,7 +55,7 @@ class JCTreeConverter(
Opcodes.ACC_SYNCHRONIZED or Opcodes.ACC_STATIC or Opcodes.ACC_NATIVE or Opcodes.ACC_DEPRECATED
private val FIELD_MODIFIERS = VISIBILITY_MODIFIERS or MODALITY_MODIFIERS or
Opcodes.ACC_STATIC or Opcodes.ACC_VOLATILE or Opcodes.ACC_TRANSIENT
Opcodes.ACC_STATIC or Opcodes.ACC_VOLATILE or Opcodes.ACC_TRANSIENT or Opcodes.ACC_ENUM
private val BLACKLISTED_ANNOTATATIONS = listOf(
"java.lang.Deprecated", "kotlin.Deprecated", // Deprecated annotations
@@ -63,8 +66,9 @@ class JCTreeConverter(
)
}
private val fileManager = context.get(JavaFileManager::class.java) as JavacFileManager
private val treeMaker = TreeMaker.instance(context)
private val nameTable = SharedNameTable(Names.instance(context))
private val nameTable = Names.instance(context).table
private var done = false
@@ -82,7 +86,7 @@ class JCTreeConverter(
// Nested classes will be processed during the outer classes conversion
if (descriptor.isNested) return null
val classDeclaration = convertClass(clazz)
val classDeclaration = convertClass(clazz, true) ?: return null
val packageAnnotations = JavacList.nil<JCAnnotation>()
val packageName = ktFile.packageFqName.asString()
@@ -91,13 +95,16 @@ class JCTreeConverter(
val imports = JavacList.nil<JCTree>()
val classes = JavacList.of<JCTree>(classDeclaration)
return treeMaker.TopLevel(packageAnnotations, packageClause, imports + classes)
val topLevel = treeMaker.TopLevel(packageAnnotations, packageClause, imports + classes)
val javaFileObject = SyntheticJavaFileObject(topLevel, classDeclaration, System.currentTimeMillis(), fileManager)
topLevel.sourcefile = javaFileObject
return topLevel
}
/**
* Returns false for the inner classe or if the origin for the class was not found.
*/
private fun convertClass(clazz: ClassNode): JCClassDecl? {
private fun convertClass(clazz: ClassNode, isTopLevel: Boolean): JCClassDecl? {
if (isSynthetic(clazz.access)) return null
val descriptor = origins[clazz]?.descriptor as? ClassDescriptor ?: return null
@@ -105,17 +112,41 @@ class JCTreeConverter(
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 isEnum = clazz.isEnum()
val isAnnotation = clazz.isAnnotation()
val isDefaultImpls = clazz.name.endsWith("${descriptor.name.asString()}/DefaultImpls")
&& isPublic(clazz.access) && isFinal(clazz.access)
&& descriptor.kind == ClassKind.INTERFACE
// DefaultImpls without any contents don't have INNERCLASS'es inside it (and inside the parent interface)
if (isDefaultImpls && (isTopLevel || (clazz.fields.isNullOrEmpty() && clazz.methods.isNullOrEmpty()))) {
return null
}
val simpleName = name(if (isDefaultImpls) "DefaultImpls" else descriptor.name.asString())
val typeParams = JavacList.nil<JCTypeParameter>()
val extending = if (clazz.superName == "java/lang/Object" || clazz.isEnum()) null else convertFqName(clazz.superName)
val implementing = mapValues(clazz.interfaces) { convertFqName(it) }
val extending = if (clazz.superName == "java/lang/Object" || isEnum) null else convertFqName(clazz.superName)
val implementing = mapValues(clazz.interfaces) {
if (isAnnotation && it == "java/lang/annotation/Annotation") return@mapValues null
convertFqName(it)
}
val fields = mapValues<FieldNode, JCTree>(clazz.fields) { convertField(it) }
val methods = mapValues<MethodNode, JCTree>(clazz.methods) { convertMethod(it, clazz, simpleName) }
val methods = mapValues<MethodNode, JCTree>(clazz.methods) {
if (isEnum) {
if (it.name == "values" && it.desc == "()[L${clazz.name};") return@mapValues null
if (it.name == "valueOf" && it.desc == "(Ljava/lang/String;)L${clazz.name};") return@mapValues null
}
convertMethod(it, clazz)
}
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
convertClass(innerClassNode)
convertClass(innerClassNode, false)
}
return treeMaker.ClassDef(modifiers, simpleName, typeParams, extending, implementing, fields + methods + nestedClasses)
@@ -127,16 +158,26 @@ class JCTreeConverter(
val modifiers = convertModifiers(field.access, ElementKind.FIELD, field.visibleAnnotations, field.invisibleAnnotations)
val name = name(field.name)
val type = Type.getType(field.desc)
val typeExpression = convertFqName(type.className)
// Enum type must be an identifier (Javac requirement)
val typeExpression = if (isEnum(field.access)) {
convertSimpleName(type.className.substringAfterLast('.'))
} else {
convertType(type)
}
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)
is Char -> treeMaker.Literal(TypeTag.CHAR, value.toInt())
is Byte, is Boolean, is Short, is Int, is Long, is Float, is Double, is String -> treeMaker.Literal(value)
else -> if (isFinal(field.access)) convertLiteralExpression(getDefaultValue(type)) else null
}
return treeMaker.VarDef(modifiers, name, typeExpression, initializer)
}
private fun convertMethod(method: MethodNode, containingClass: ClassNode, containingClassSimpleName: Name): JCMethodDecl? {
private fun convertMethod(method: MethodNode, containingClass: ClassNode): JCMethodDecl? {
if (isSynthetic(method.access)) return null
val descriptor = origins[method]?.descriptor as? CallableDescriptor ?: return null
@@ -147,22 +188,24 @@ class JCTreeConverter(
method.visibleAnnotations
}
val modifiers = convertModifiers(method.access, ElementKind.METHOD, visibleAnnotations, method.invisibleAnnotations)
val modifiers = convertModifiers(
if (containingClass.isEnum()) (method.access and VISIBILITY_MODIFIERS.inv()) else method.access,
ElementKind.METHOD, visibleAnnotations, method.invisibleAnnotations)
val isConstructor = method.name == "<init>"
val name = if (isConstructor) containingClassSimpleName else name(method.name)
val name = name(method.name)
val typeParameters = JavacList.nil<JCTypeParameter>()
val receiverParameter = null
val returnType = Type.getReturnType(method.desc)
val returnTypeExpr = if (isConstructor) null else convertFqName(returnType.className)
val returnTypeExpr = if (isConstructor) null else convertType(returnType)
val parametersInfo = method.getParametersInfo()
val parametersInfo = method.getParametersInfo(containingClass)
@Suppress("NAME_SHADOWING")
val parameters = mapValues(parametersInfo) { info ->
val modifiers = convertModifiers(info.access, ElementKind.PARAMETER, info.visibleAnnotations, info.invisibleAnnotations)
val name = name(info.name)
val type = convertFqName(info.type)
val type = convertType(info.type)
treeMaker.VarDef(modifiers, name, type, null)
}
@@ -172,8 +215,10 @@ class JCTreeConverter(
val body = if (defaultValue != null) {
null
} else if ((method.access and Opcodes.ACC_ABSTRACT) > 0) {
} else if (isAbstract(method.access)) {
null
} else if (isConstructor && containingClass.isEnum()) {
treeMaker.Block(0, JavacList.nil())
} else if (isConstructor) {
// We already checked it in convertClass()
val declaration = origins[containingClass]?.descriptor as ClassDescriptor
@@ -226,10 +271,11 @@ class JCTreeConverter(
}
private fun convertAnnotation(annotation: AnnotationNode): JCAnnotation? {
val fqName = Type.getType(annotation.desc).className
val annotationType = Type.getType(annotation.desc)
val fqName = annotationType.className
if (BLACKLISTED_ANNOTATATIONS.any { fqName.startsWith(it) }) return null
val name = convertFqName(fqName)
val name = convertType(annotationType)
val values = mapPairedValues<JCExpression>(annotation.values) { key, value ->
treeMaker.Assign(convertSimpleName(key), convertLiteralExpression(value))
}
@@ -238,8 +284,9 @@ class JCTreeConverter(
private fun convertLiteralExpression(value: Any?): JCExpression {
return when (value) {
null -> convertSimpleName("null")
is Byte, is Boolean, is Char, is Short, is Int, is Long, is Float, is Double, is String -> treeMaker.Literal(value)
null -> treeMaker.Literal(TypeTag.BOT, null)
is Char -> treeMaker.Literal(TypeTag.CHAR, value.toInt())
is Byte, is Boolean, is Short, is Int, is Long, is Float, is Double, is String -> treeMaker.Literal(value)
is ByteArray -> treeMaker.NewArray(null, JavacList.nil(), mapValues(value.asIterable()) { convertLiteralExpression(it) })
is BooleanArray -> treeMaker.NewArray(null, JavacList.nil(), mapValues(value.asIterable()) { convertLiteralExpression(it) })
@@ -249,10 +296,15 @@ class JCTreeConverter(
is LongArray -> treeMaker.NewArray(null, JavacList.nil(), mapValues(value.asIterable()) { convertLiteralExpression(it) })
is FloatArray -> treeMaker.NewArray(null, JavacList.nil(), mapValues(value.asIterable()) { convertLiteralExpression(it) })
is DoubleArray -> treeMaker.NewArray(null, JavacList.nil(), mapValues(value.asIterable()) { convertLiteralExpression(it) })
is Array<*> -> treeMaker.NewArray(null, JavacList.nil(), mapValues(value.asIterable()) { convertLiteralExpression(it) })
is Array<*> -> { // Two-element String array for enumerations ([desc, fieldName])
assert(value.size == 2)
val enumType = Type.getType(value[0] as String)
val valueName = value[1] as String
treeMaker.Select(convertType(enumType), name(valueName))
}
is List<*> -> treeMaker.NewArray(null, JavacList.nil(), mapValues(value) { convertLiteralExpression(it) })
is Type -> treeMaker.Select(convertFqName(value.className), name("class"))
is Type -> treeMaker.Select(convertType(value), name("class"))
is AnnotationNode -> convertAnnotation(value) ?: error("Annotation is filtered out")
else -> throw IllegalArgumentException("Illegal literal expression value: $value (${value.javaClass.canonicalName})")
}
@@ -270,6 +322,14 @@ class JCTreeConverter(
else -> null
}
private fun convertType(type: Type): JCExpression {
convertBuiltinType(type)?.let { return it }
if (type.sort == Type.ARRAY) {
return treeMaker.TypeArray(convertType(type.elementType))
}
return convertFqName(type.className)
}
private fun convertFqName(internalOrFqName: String): JCExpression {
val path = internalOrFqName.replace('/', '.').split('.')
assert(path.isNotEmpty())
@@ -282,7 +342,23 @@ class JCTreeConverter(
return expr
}
private fun convertSimpleName(name: String): JCIdent = treeMaker.Ident(name(name))
private fun convertBuiltinType(type: Type): JCExpression? {
val typeTag = when (type) {
Type.BYTE_TYPE -> TypeTag.BYTE
Type.BOOLEAN_TYPE -> TypeTag.BOOLEAN
Type.CHAR_TYPE -> TypeTag.CHAR
Type.SHORT_TYPE -> TypeTag.SHORT
Type.INT_TYPE -> TypeTag.INT
Type.LONG_TYPE -> TypeTag.LONG
Type.FLOAT_TYPE -> TypeTag.FLOAT
Type.DOUBLE_TYPE -> TypeTag.DOUBLE
Type.VOID_TYPE -> TypeTag.VOID
else -> null
} ?: return null
return treeMaker.TypeIdent(typeTag)
}
private fun convertSimpleName(name: String): JCExpression = treeMaker.Ident(name(name))
private fun name(name: String) = nameTable.fromString(name)
}
@@ -290,21 +366,38 @@ class JCTreeConverter(
private class ParameterInfo(
val access: Int,
val name: String,
val type: String,
val type: Type,
val visibleAnnotations: List<AnnotationNode>?,
val invisibleAnnotations: List<AnnotationNode>?)
private fun MethodNode.getParametersInfo(): List<ParameterInfo> {
private fun MethodNode.getParametersInfo(containingClass: ClassNode): List<ParameterInfo> {
val localVariables = this.localVariables ?: emptyList()
val parameters = this.parameters ?: emptyList()
val isStatic = (access and Opcodes.ACC_STATIC) > 0
val isStatic = isStatic(access)
// First and second parameters in enum constructors are synthetic, we should ignore them
val isEnumConstructor = (name == "<init>") && containingClass.isEnum()
val startParameterIndex = if (isEnumConstructor) 2 else 0
val parameterTypes = Type.getArgumentTypes(desc)
return parameterTypes.mapIndexed { index, type ->
val name = parameters.getOrNull(index)?.name ?: localVariables.getOrNull(index + (if (isStatic) 0 else 1))?.name ?: "p$index"
val parameterInfos = ArrayList<ParameterInfo>(parameterTypes.size - startParameterIndex)
for (index in startParameterIndex..parameterTypes.lastIndex) {
val type = parameterTypes[index]
var name = parameters.getOrNull(index - startParameterIndex)?.name
?: localVariables.getOrNull(index + (if (isStatic) 0 else 1))?.name
?: "p${index - startParameterIndex}"
// Property setters has bad parameter names
if (name.startsWith("<") && name.endsWith(">")) {
name = "p${index - startParameterIndex}"
}
val visibleAnnotations = visibleParameterAnnotations?.get(index)
val invisibleAnnotations = invisibleParameterAnnotations?.get(index)
ParameterInfo(0, name, type.className, visibleAnnotations, invisibleAnnotations)
parameterInfos += ParameterInfo(0, name, type, visibleAnnotations, invisibleAnnotations)
}
return parameterInfos
}
private inline fun <T, R> mapValues(values: Iterable<T>?, f: (T) -> R?): JavacList<R> {
@@ -340,7 +433,13 @@ private operator fun <T : Any> JavacList<T>.plus(other: JavacList<T>): JavacList
private val ClassDescriptor.isNested: Boolean
get() = containingDeclaration is ClassDescriptor
private fun isEnum(access: Int) = (access and Opcodes.ACC_ENUM) > 0
private fun isPublic(access: Int) = (access and Opcodes.ACC_PUBLIC) > 0
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
private fun isAbstract(access: Int) = (access and Opcodes.ACC_ABSTRACT) > 0
private fun ClassNode.isEnum() = (access and Opcodes.ACC_ENUM) > 0
private fun ClassNode.isAnnotation() = (access and Opcodes.ACC_ANNOTATION) > 0
private fun <T> List<T>.isNullOrEmpty() = this == null || this.isEmpty()
@@ -24,10 +24,8 @@ import com.sun.tools.javac.processing.AnnotationProcessingError
import com.sun.tools.javac.processing.JavacProcessingEnvironment
import com.sun.tools.javac.tree.JCTree
import com.sun.tools.javac.util.Context
import com.sun.tools.javac.util.Log
import com.sun.tools.javac.util.Options
import java.io.File
import java.io.PrintWriter
import javax.annotation.processing.Processor
import javax.tools.JavaFileManager
import com.sun.tools.javac.util.List as JavacList
@@ -52,14 +50,16 @@ class KaptError : RuntimeException {
class KaptRunner {
val context = Context()
val compiler: KaptJavaCompiler
private val options: Options
init {
JavacFileManager.preRegister(context)
KaptJavaCompiler.preRegister(context)
compiler = JavaCompiler.instance(context) as KaptJavaCompiler
options = Options.instance(context)
context.put(Log.outKey, PrintWriter(System.err, true))
}
fun parseJavaFiles(
@@ -69,7 +69,6 @@ class KaptRunner {
classpath.forEach { options.put(Option.CLASSPATH, it.canonicalPath) }
val fileManager = context.get(JavaFileManager::class.java) as JavacFileManager
val compiler = JavaCompiler.instance(context) as KaptJavaCompiler
try {
val javaFileObjects = fileManager.getJavaFileObjectsFromFiles(javaSourceFiles)
@@ -93,7 +92,6 @@ class KaptRunner {
options.put(Option.D, classOutputDir.canonicalPath)
val fileManager = context.get(JavaFileManager::class.java) as JavacFileManager
val compiler = JavaCompiler.instance(context) as KaptJavaCompiler
val processingEnvironment = JavacProcessingEnvironment.instance(context)
try {
@@ -0,0 +1,91 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.kapt3
import com.sun.tools.javac.file.BaseFileObject
import com.sun.tools.javac.file.JavacFileManager
import com.sun.tools.javac.tree.JCTree
import java.io.*
import java.net.URI
import java.net.URL
import javax.lang.model.element.Modifier
import javax.lang.model.element.NestingKind
import javax.tools.JavaFileObject
class SyntheticJavaFileObject(
val compilationUnit: JCTree.JCCompilationUnit,
val clazz: JCTree.JCClassDecl,
val timestamp: Long,
fileManager: JavacFileManager
) : BaseFileObject(fileManager) {
override fun getShortName() = clazz.simpleName.toString()
override fun inferBinaryName(path: MutableIterable<File>?) = throw UnsupportedOperationException()
override fun isNameCompatible(simpleName: String?, kind: JavaFileObject.Kind?) = true
override fun getKind() = JavaFileObject.Kind.SOURCE
override fun getName() = compilationUnit.packageName.toString().replace('.', '/') + clazz.name + ".java"
override fun getAccessLevel(): Modifier? {
val flags = clazz.modifiers.getFlags()
if (Modifier.PUBLIC in flags) return Modifier.PUBLIC
if (Modifier.PROTECTED in flags) return Modifier.PROTECTED
if (Modifier.PRIVATE in flags) return Modifier.PRIVATE
return null
}
override fun openInputStream() = getCharContent(false).byteInputStream()
override fun getCharContent(ignoreEncodingErrors: Boolean) = compilationUnit.toString()
override fun getNestingKind() = NestingKind.TOP_LEVEL
override fun toUri(): URI? = URL(name).toURI()
override fun openReader(ignoreEncodingErrors: Boolean) = getCharContent(ignoreEncodingErrors).reader()
override fun openWriter() = throw UnsupportedOperationException()
override fun getLastModified() = timestamp
override fun openOutputStream() = throw UnsupportedOperationException()
override fun delete() = throw UnsupportedOperationException()
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other?.javaClass != javaClass) return false
other as SyntheticJavaFileObject
if (compilationUnit != other.compilationUnit) return false
if (clazz != other.clazz) return false
if (timestamp != other.timestamp) return false
return true
}
override fun hashCode(): Int {
var result = 0
result = 31 * result + compilationUnit.hashCode()
result = 31 * result + clazz.hashCode()
result = 31 * result + timestamp.hashCode()
return result
}
}
@@ -16,6 +16,8 @@
package org.jetbrains.kotlin.kapt3.test
import com.intellij.openapi.util.text.StringUtil
import com.sun.tools.javac.comp.CompileStates
import org.jetbrains.kotlin.codegen.CodegenTestCase
import org.jetbrains.kotlin.codegen.CodegenTestUtil
import org.jetbrains.kotlin.kapt3.JCTreeConverter
@@ -23,6 +25,7 @@ import org.jetbrains.kotlin.kapt3.Kapt3BuilderFactory
import org.jetbrains.kotlin.kapt3.KaptRunner
import org.jetbrains.kotlin.test.ConfigurationKind
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.test.util.trimTrailingWhitespacesAndAddNewlineAtEOF
import java.io.File
abstract class AbstractJCTreeConverterTest : CodegenTestCase() {
@@ -38,10 +41,23 @@ abstract class AbstractJCTreeConverterTest : CodegenTestCase() {
val typeMapper = factory.generationState.typeMapper
val kaptRunner = KaptRunner()
val converter = JCTreeConverter(kaptRunner.context, typeMapper, classBuilderFactory.compiledClasses, classBuilderFactory.origins)
val javaFiles = converter.convert()
try {
val converter = JCTreeConverter(kaptRunner.context, typeMapper, classBuilderFactory.compiledClasses, classBuilderFactory.origins)
val javaFiles = converter.convert()
KotlinTestUtils.assertEqualsToFile(txtFile, javaFiles.joinToString("\n\n////////////////////\n\n"))
kaptRunner.compiler.enterTrees(javaFiles)
val actualRaw = javaFiles.joinToString ("\n\n////////////////////\n\n")
val actual = StringUtil.convertLineSeparators(actualRaw.trim({ it <= ' ' })).trimTrailingWhitespacesAndAddNewlineAtEOF()
if (kaptRunner.compiler.shouldStop(CompileStates.CompileState.ENTER)) {
error("There were errors during analysis. See errors above. Stubs:\n\n$actual")
}
KotlinTestUtils.assertEqualsToFile(txtFile, actual)
} finally {
kaptRunner.compiler.close()
}
}
}
@@ -35,18 +35,48 @@ public class JCTreeConverterTestGenerated extends AbstractJCTreeConverterTest {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("plugins/kapt3/testData/converter"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("annotations.kt")
public void testAnnotations() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("plugins/kapt3/testData/converter/annotations.kt");
doTest(fileName);
}
@TestMetadata("dataClass.kt")
public void testDataClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("plugins/kapt3/testData/converter/dataClass.kt");
doTest(fileName);
}
@TestMetadata("defaultImpls.kt")
public void testDefaultImpls() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("plugins/kapt3/testData/converter/defaultImpls.kt");
doTest(fileName);
}
@TestMetadata("enums.kt")
public void testEnums() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("plugins/kapt3/testData/converter/enums.kt");
doTest(fileName);
}
@TestMetadata("functions.kt")
public void testFunctions() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("plugins/kapt3/testData/converter/functions.kt");
doTest(fileName);
}
@TestMetadata("inheritanceSimple.kt")
public void testInheritanceSimple() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("plugins/kapt3/testData/converter/inheritanceSimple.kt");
doTest(fileName);
}
@TestMetadata("jvmStatic.kt")
public void testJvmStatic() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("plugins/kapt3/testData/converter/jvmStatic.kt");
doTest(fileName);
}
@TestMetadata("nestedClasses.kt")
public void testNestedClasses() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("plugins/kapt3/testData/converter/nestedClasses.kt");
+31
View File
@@ -0,0 +1,31 @@
annotation class Anno1
enum class Colors { WHITE, BLACK }
annotation class Anno2(
val i: Int = 5,
val s: String = "ABC",
val ii: IntArray = intArrayOf(1, 2, 3),
val ss: Array<String> = arrayOf("A", "B"),
val a: Anno1,
val color: Colors = Colors.BLACK,
val colors: Array<Colors> = arrayOf(Colors.BLACK, Colors.WHITE),
val clazz: kotlin.reflect.KClass<*>,
val classes: Array<kotlin.reflect.KClass<*>>
)
annotation class Anno3(val value: String)
@Anno1
@Anno2(a = Anno1(), clazz = TestAnno::class, classes = arrayOf(TestAnno::class, Anno1::class))
@Anno3(value = "value")
class TestAnno
@Anno3("value")
@Anno2(i = 6, s = "BCD", ii = intArrayOf(4, 5, 6), ss = arrayOf("Z", "X"),
a = Anno1(), color = Colors.WHITE, colors = arrayOf(Colors.WHITE),
clazz = TestAnno::class, classes = arrayOf(TestAnno::class, Anno1::class))
class TestAnno2 {
@Anno1
fun a(@Anno3("param-pam-pam") param: String) {}
@get:Anno3("getter") @set:Anno3("setter") @property:Anno3("property") @field:Anno3("field") @setparam:Anno3("setparam")
var b: String = "property initializer"
}
+87
View File
@@ -0,0 +1,87 @@
public abstract @interface Anno1 {
}
////////////////////
public enum Colors {
/*public static final*/ WHITE /* = null */,
/*public static final*/ BLACK /* = null */;
Colors() {
}
}
////////////////////
public abstract @interface Anno2 {
public abstract int i() default 5;
public abstract java.lang.String s() default "ABC";
public abstract int[] ii() default {1, 2, 3};
public abstract java.lang.String[] ss() default {"A", "B"};
public abstract Anno1 a();
public abstract Colors color() default Colors.BLACK;
public abstract Colors[] colors() default {Colors.BLACK, Colors.WHITE};
public abstract java.lang.Class clazz();
public abstract java.lang.Class[] classes();
}
////////////////////
public abstract @interface Anno3 {
public abstract java.lang.String value();
}
////////////////////
@Anno3(value = "value")
@Anno2(a = @Anno1(), clazz = TestAnno.class, classes = {TestAnno.class, Anno1.class})
@Anno1()
public final class TestAnno {
public TestAnno() {
super();
}
}
////////////////////
@Anno2(i = 6, s = "BCD", ii = {4, 5, 6}, ss = {"Z", "X"}, a = @Anno1(), color = Colors.WHITE, colors = {Colors.WHITE}, clazz = TestAnno.class, classes = {TestAnno.class, Anno1.class})
@Anno3(value = "value")
public final class TestAnno2 {
@Anno3(value = "field")
private java.lang.String b;
@Anno1()
public final void a(@Anno3(value = "param-pam-pam")
java.lang.String param) {
}
@Anno3(value = "getter")
public final java.lang.String getB() {
return null;
}
@Anno3(value = "setter")
public final void setB(@Anno3(value = "setparam")
java.lang.String p0) {
}
public TestAnno2() {
super();
}
}
+1 -1
View File
@@ -19,7 +19,7 @@ public final class User {
return 0;
}
public /*missing*/ User(java.lang.String firstName, java.lang.String secondName, int age) {
public User(java.lang.String firstName, java.lang.String secondName, int age) {
super();
}
+15
View File
@@ -0,0 +1,15 @@
interface IntfWithoutDefaultImpls
interface IntfWithDefaultImpls {
fun a() {}
}
interface Intf {
companion object {
val BLACK = 1
const val WHITE = 2
}
val color: Int
get() = BLACK
}
+54
View File
@@ -0,0 +1,54 @@
public abstract interface IntfWithoutDefaultImpls {
}
////////////////////
public abstract interface IntfWithDefaultImpls {
public abstract void a();
public static final class DefaultImpls {
public DefaultImpls() {
super();
}
public static void a(IntfWithDefaultImpls $this) {
}
}
}
////////////////////
public abstract interface Intf {
public static final Intf.Companion Companion = null;
public static final int WHITE = 2;
public abstract int getColor();
public static final class DefaultImpls {
public DefaultImpls() {
super();
}
public static int getColor(Intf $this) {
return 0;
}
}
public static final class Companion {
private static final int BLACK = 1;
public static final int WHITE = 2;
public final int getBLACK() {
return 0;
}
private Companion() {
super();
}
}
}
+10
View File
@@ -0,0 +1,10 @@
enum class Enum1 {
BLACK, WHITE
}
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
}
+42
View File
@@ -0,0 +1,42 @@
public enum Enum1 {
/*public static final*/ BLACK /* = null */,
/*public static final*/ WHITE /* = null */;
Enum1() {
}
}
////////////////////
public abstract @interface Anno1 {
public abstract java.lang.String value();
}
////////////////////
public enum Enum2 {
/*public static final*/ RED /* = null */,
/*public static final*/ WHITE /* = null */;
private final java.lang.String col = null;
private final int col2 = 0;
final java.lang.String color() {
return null;
}
final java.lang.String getCol() {
return null;
}
final int getCol2() {
return 0;
}
Enum2(@Anno1(value = "first")
java.lang.String col, @Anno1(value = "second")
int col2) {
}
}
+6
View File
@@ -0,0 +1,6 @@
class FunctionsTest {
fun f() = String::length
fun f2() = fun (a: Int, b: Int) = a > b
fun f3() = run {}
fun f4() = run { 3 }
}
+22
View File
@@ -0,0 +1,22 @@
public final class FunctionsTest {
public final kotlin.reflect.KProperty1 f() {
return null;
}
public final kotlin.jvm.functions.Function2 f2() {
return null;
}
public final void f3() {
}
public final int f4() {
return 0;
}
public FunctionsTest() {
super();
}
}
+11 -28
View File
@@ -1,31 +1,14 @@
public abstract interface Context {
}
////////////////////
public final class Context {
}
////////////////////
public enum Result {
;
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);
}
public static Result[] values() {
return null;
}
public static Result valueOf(java.lang.String p0) {
return null;
/*public static final*/ SUCCESS /* = null */,
/*public static final*/ ERROR /* = null */;
Result() {
}
}
@@ -33,10 +16,10 @@ public enum Result {
public abstract class BaseClass {
public abstract Result doJob();
public /*missing*/ BaseClass(Context context, int num, boolean bool) {
public BaseClass(Context context, int num, boolean bool) {
super();
}
}
@@ -45,13 +28,13 @@ public abstract class BaseClass {
public final class Inheritor extends BaseClass {
@java.lang.Override()
public Result doJob() {
return null;
}
public /*missing*/ Inheritor(Context context) {
public Inheritor(Context context) {
super(null, 0, false);
}
}
}
+13
View File
@@ -0,0 +1,13 @@
class JvmStaticTest {
companion object {
@JvmStatic
val one = 1
val two = 2
const val c: Char = 'C'
}
val three: Byte = 3.toByte()
val d: Char = 'D'
}
+40
View File
@@ -0,0 +1,40 @@
public final class JvmStaticTest {
private final byte three = "3";
private final char d = 'D';
private static final int one = 1;
private static final int two = 2;
public static final char c = 'C';
public static final JvmStaticTest.Companion Companion = null;
public final byte getThree() {
return "0";
}
public final char getD() {
return '\u0000';
}
public JvmStaticTest() {
super();
}
public static final int getOne() {
return 0;
}
public static final class Companion {
public final int getOne() {
return 0;
}
public final int getTwo() {
return 0;
}
private Companion() {
super();
}
}
}
+9 -20
View File
@@ -1,19 +1,18 @@
public final class Test {
public /*missing*/ Test() {
public Test() {
super();
}
public static final class Nested {
public /*missing*/ Nested() {
public Nested() {
super();
}
public static final class NestedNested {
public /*missing*/ NestedNested() {
public NestedNested() {
super();
}
}
@@ -21,7 +20,7 @@ public final class Test {
public final class Inner {
public /*missing*/ Inner(Test $outer) {
public Inner(Test $outer) {
super();
}
}
@@ -29,7 +28,7 @@ public final class Test {
public static final class NestedObject {
public static final Test.NestedObject INSTANCE = null;
private /*missing*/ NestedObject() {
private NestedObject() {
super();
}
}
@@ -38,20 +37,10 @@ public final class Test {
}
public static enum NestedEnum {
;
public static final Test.NestedEnum BLACK = null;
public static final Test.NestedEnum WHITE = null;
/*public static final*/ BLACK /* = null */,
/*public static final*/ 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;
NestedEnum() {
}
}
}
}