Add kotlinp, a tool to print Kotlin metadata in class/module files
At the moment, it's not published anywhere, but that may change soon #KT-23198
This commit is contained in:
@@ -46,6 +46,7 @@ class CodeConformanceTest : TestCase() {
|
|||||||
"dist",
|
"dist",
|
||||||
"libraries/tools/kotlin-gradle-plugin-core/gradle_api_jar/build/tmp",
|
"libraries/tools/kotlin-gradle-plugin-core/gradle_api_jar/build/tmp",
|
||||||
"libraries/tools/kotlin-maven-plugin/target",
|
"libraries/tools/kotlin-maven-plugin/target",
|
||||||
|
"libraries/tools/kotlinp/src",
|
||||||
"compiler/testData/psi/kdoc",
|
"compiler/testData/psi/kdoc",
|
||||||
"compiler/tests/org/jetbrains/kotlin/code/CodeConformanceTest.kt",
|
"compiler/tests/org/jetbrains/kotlin/code/CodeConformanceTest.kt",
|
||||||
"compiler/util/src/org/jetbrains/kotlin/config/MavenComparableVersion.java"
|
"compiler/util/src/org/jetbrains/kotlin/config/MavenComparableVersion.java"
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
||||||
|
|
||||||
|
description = "kotlinp"
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
kotlin("jvm")
|
||||||
|
}
|
||||||
|
|
||||||
|
val shadows by configurations.creating
|
||||||
|
shadows.extendsFrom(configurations.getByName("compile"))
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile(project(":kotlinx-metadata"))
|
||||||
|
compile(project(":kotlinx-metadata-jvm"))
|
||||||
|
// We use an older version of ASM on purpose, to reduce the final application size
|
||||||
|
compile("org.ow2.asm:asm:4.0")
|
||||||
|
testCompile(commonDep("junit:junit"))
|
||||||
|
testCompile(projectTests(":generators:test-generator"))
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
"main" { projectDefault() }
|
||||||
|
"test" { projectDefault() }
|
||||||
|
}
|
||||||
|
|
||||||
|
projectTest {
|
||||||
|
workingDir = rootDir
|
||||||
|
}
|
||||||
|
|
||||||
|
val generateTests by generator("org.jetbrains.kotlin.kotlinp.test.GenerateKotlinpTestsKt")
|
||||||
|
|
||||||
|
val shadowJar by task<ShadowJar> {
|
||||||
|
classifier = "shadow"
|
||||||
|
version = null
|
||||||
|
configurations = listOf(shadows)
|
||||||
|
from(the<JavaPluginConvention>().sourceSets.getByName("main").output)
|
||||||
|
manifest {
|
||||||
|
attributes["Main-Class"] = "org.jetbrains.kotlin.kotlinp.Main"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.kotlinp
|
||||||
|
|
||||||
|
import kotlinx.metadata.InconsistentKotlinMetadataException
|
||||||
|
import kotlinx.metadata.jvm.KotlinClassMetadata
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
object Kotlinp {
|
||||||
|
internal fun renderClassFile(classFile: KotlinClassMetadata?): String =
|
||||||
|
when (classFile) {
|
||||||
|
is KotlinClassMetadata.Class -> ClassPrinter().print(classFile)
|
||||||
|
is KotlinClassMetadata.FileFacade -> FileFacadePrinter().print(classFile)
|
||||||
|
is KotlinClassMetadata.SyntheticClass -> {
|
||||||
|
if (classFile.isLambda) LambdaPrinter().print(classFile)
|
||||||
|
else buildString { appendln("synthetic class") }
|
||||||
|
}
|
||||||
|
is KotlinClassMetadata.MultiFileClassFacade -> MultiFileClassFacadePrinter().print(classFile)
|
||||||
|
is KotlinClassMetadata.MultiFileClassPart -> MultiFileClassPartPrinter().print(classFile)
|
||||||
|
is KotlinClassMetadata.Unknown -> buildString { appendln("unknown file (k=${classFile.header.kind})") }
|
||||||
|
null -> buildString { appendln("unsupported file") }
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun readClassFile(file: File): KotlinClassMetadata? {
|
||||||
|
val header = file.readKotlinClassHeader() ?: throw KotlinpException("file is not a Kotlin class file: $file")
|
||||||
|
return try {
|
||||||
|
KotlinClassMetadata.read(header)
|
||||||
|
} catch (e: InconsistentKotlinMetadataException) {
|
||||||
|
throw KotlinpException("inconsistent Kotlin metadata: ${e.message}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.kotlinp
|
||||||
|
|
||||||
|
class KotlinpException(message: String) : RuntimeException(message)
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.kotlinp
|
||||||
|
|
||||||
|
import java.io.File
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
|
object Main {
|
||||||
|
private fun run(args: Array<String>) {
|
||||||
|
val paths = arrayListOf<String>()
|
||||||
|
|
||||||
|
var i = 0
|
||||||
|
while (true) {
|
||||||
|
val arg = args.getOrNull(i++) ?: break
|
||||||
|
|
||||||
|
if ("-help" == arg || "-h" == arg) {
|
||||||
|
printUsageAndExit()
|
||||||
|
} else if ("-version" == arg) {
|
||||||
|
printVersionAndExit()
|
||||||
|
} else if (arg.startsWith("-")) {
|
||||||
|
throw KotlinpException("unsupported argument: $arg")
|
||||||
|
} else {
|
||||||
|
paths.add(arg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (path in paths) {
|
||||||
|
if (!path.endsWith(".class")) throw KotlinpException("only .class files are supported")
|
||||||
|
|
||||||
|
val file = File(path)
|
||||||
|
if (!file.exists()) throw KotlinpException("file does not exist: $path")
|
||||||
|
|
||||||
|
try {
|
||||||
|
print(Kotlinp.renderClassFile(Kotlinp.readClassFile(file)))
|
||||||
|
} catch (e: IOException) {
|
||||||
|
throw KotlinpException("I/O operation failed: ${e.message}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (paths.isEmpty()) {
|
||||||
|
throw KotlinpException("no files specified")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
try {
|
||||||
|
run(args)
|
||||||
|
} catch (e: KotlinpException) {
|
||||||
|
System.err.println("error: " + e.message)
|
||||||
|
System.exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun printUsageAndExit() {
|
||||||
|
println(
|
||||||
|
"""kotlinp: print Kotlin declarations in the given class file.
|
||||||
|
|
||||||
|
Usage: kotlinp <options> <classes>
|
||||||
|
where possible options include:
|
||||||
|
-version Display Kotlin version
|
||||||
|
-help (-h) Print a synopsis of options
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
System.exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun printVersionAndExit() {
|
||||||
|
// TODO: get version from manifest
|
||||||
|
val version = "@snapshot@"
|
||||||
|
|
||||||
|
println("Kotlin version " + version + " (JRE " + System.getProperty("java.runtime.version") + ")")
|
||||||
|
System.exit(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,731 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.kotlinp
|
||||||
|
|
||||||
|
import kotlinx.metadata.*
|
||||||
|
import kotlinx.metadata.jvm.*
|
||||||
|
|
||||||
|
private object SpecialCharacters {
|
||||||
|
const val TYPE_ALIAS_MARKER = '^'
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun visitFunction(sb: StringBuilder, flags: Int, name: String): KmFunctionVisitor =
|
||||||
|
object : KmFunctionVisitor() {
|
||||||
|
val typeParams = mutableListOf<String>()
|
||||||
|
val params = mutableListOf<String>()
|
||||||
|
var receiverParameterType: String? = null
|
||||||
|
var returnType: String? = null
|
||||||
|
var versionRequirement: String? = null
|
||||||
|
var jvmDesc: String? = null
|
||||||
|
|
||||||
|
override fun visitReceiverParameterType(flags: Int): KmTypeVisitor? =
|
||||||
|
printType(flags) { receiverParameterType = it }
|
||||||
|
|
||||||
|
override fun visitTypeParameter(
|
||||||
|
flags: Int, name: String, id: Int, variance: KmVariance
|
||||||
|
): KmTypeParameterVisitor? =
|
||||||
|
printTypeParameter(flags, name, id, variance) { typeParams.add(it) }
|
||||||
|
|
||||||
|
override fun visitValueParameter(flags: Int, name: String): KmValueParameterVisitor? =
|
||||||
|
printValueParameter(flags, name) { params.add(it) }
|
||||||
|
|
||||||
|
override fun visitReturnType(flags: Int): KmTypeVisitor? =
|
||||||
|
printType(flags) { returnType = it }
|
||||||
|
|
||||||
|
override fun visitVersionRequirement(): KmVersionRequirementVisitor? =
|
||||||
|
printVersionRequirement { versionRequirement = it }
|
||||||
|
|
||||||
|
override fun visitExtensions(type: KmExtensionType): KmFunctionExtensionVisitor? {
|
||||||
|
if (type != JvmFunctionExtensionVisitor.TYPE) return null
|
||||||
|
return object : JvmFunctionExtensionVisitor() {
|
||||||
|
override fun visit(desc: String?) {
|
||||||
|
jvmDesc = desc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitEnd() {
|
||||||
|
sb.appendln()
|
||||||
|
if (versionRequirement != null) {
|
||||||
|
sb.appendln(" // $versionRequirement")
|
||||||
|
}
|
||||||
|
if (jvmDesc != null) {
|
||||||
|
sb.appendln(" // signature: $jvmDesc")
|
||||||
|
}
|
||||||
|
sb.append(" ")
|
||||||
|
sb.appendFlags(flags, FUNCTION_FLAGS_MAP)
|
||||||
|
sb.append("fun ")
|
||||||
|
if (typeParams.isNotEmpty()) {
|
||||||
|
typeParams.joinTo(sb, prefix = "<", postfix = ">")
|
||||||
|
sb.append(" ")
|
||||||
|
}
|
||||||
|
if (receiverParameterType != null) {
|
||||||
|
sb.append(receiverParameterType).append(".")
|
||||||
|
}
|
||||||
|
sb.append(name)
|
||||||
|
params.joinTo(sb, prefix = "(", postfix = ")")
|
||||||
|
if (returnType != null) {
|
||||||
|
sb.append(": ").append(returnType)
|
||||||
|
}
|
||||||
|
sb.appendln()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun visitProperty(sb: StringBuilder, flags: Int, name: String, getterFlags: Int, setterFlags: Int): KmPropertyVisitor =
|
||||||
|
object : KmPropertyVisitor() {
|
||||||
|
val typeParams = mutableListOf<String>()
|
||||||
|
var receiverParameterType: String? = null
|
||||||
|
var returnType: String? = null
|
||||||
|
var setterParameter: String? = null
|
||||||
|
var versionRequirement: String? = null
|
||||||
|
var jvmFieldName: String? = null
|
||||||
|
var jvmFieldTypeDesc: String? = null
|
||||||
|
var jvmGetterDesc: String? = null
|
||||||
|
var jvmSetterDesc: String? = null
|
||||||
|
var jvmSyntheticMethodForAnnotationsDesc: String? = null
|
||||||
|
|
||||||
|
override fun visitReceiverParameterType(flags: Int): KmTypeVisitor? =
|
||||||
|
printType(flags) { receiverParameterType = it }
|
||||||
|
|
||||||
|
override fun visitTypeParameter(flags: Int, name: String, id: Int, variance: KmVariance): KmTypeParameterVisitor? =
|
||||||
|
printTypeParameter(flags, name, id, variance) { typeParams.add(it) }
|
||||||
|
|
||||||
|
override fun visitSetterParameter(flags: Int, name: String): KmValueParameterVisitor? =
|
||||||
|
printValueParameter(flags, name) { setterParameter = it }
|
||||||
|
|
||||||
|
override fun visitReturnType(flags: Int): KmTypeVisitor? =
|
||||||
|
printType(flags) { returnType = it }
|
||||||
|
|
||||||
|
override fun visitVersionRequirement(): KmVersionRequirementVisitor? =
|
||||||
|
printVersionRequirement { versionRequirement = it }
|
||||||
|
|
||||||
|
override fun visitExtensions(type: KmExtensionType): KmPropertyExtensionVisitor? {
|
||||||
|
if (type != JvmPropertyExtensionVisitor.TYPE) return null
|
||||||
|
return object : JvmPropertyExtensionVisitor() {
|
||||||
|
override fun visit(fieldName: String?, fieldTypeDesc: String?, getterDesc: String?, setterDesc: String?) {
|
||||||
|
jvmFieldName = fieldName
|
||||||
|
jvmFieldTypeDesc = fieldTypeDesc
|
||||||
|
jvmGetterDesc = getterDesc
|
||||||
|
jvmSetterDesc = setterDesc
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitSyntheticMethodForAnnotations(desc: String?) {
|
||||||
|
jvmSyntheticMethodForAnnotationsDesc = desc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitEnd() {
|
||||||
|
sb.appendln()
|
||||||
|
if (versionRequirement != null) {
|
||||||
|
sb.appendln(" // $versionRequirement")
|
||||||
|
}
|
||||||
|
if (jvmFieldName != null || jvmFieldTypeDesc != null) {
|
||||||
|
sb.append(" // field: ${jvmFieldName ?: "<null>"}")
|
||||||
|
if (jvmFieldTypeDesc != null) {
|
||||||
|
sb.append(":$jvmFieldTypeDesc")
|
||||||
|
}
|
||||||
|
sb.appendln()
|
||||||
|
}
|
||||||
|
if (jvmGetterDesc != null) {
|
||||||
|
sb.appendln(" // getter: $jvmGetterDesc")
|
||||||
|
}
|
||||||
|
if (jvmSetterDesc != null) {
|
||||||
|
sb.appendln(" // setter: $jvmSetterDesc")
|
||||||
|
}
|
||||||
|
if (jvmSyntheticMethodForAnnotationsDesc != null) {
|
||||||
|
sb.appendln(" // synthetic method for annotations: $jvmSyntheticMethodForAnnotationsDesc")
|
||||||
|
}
|
||||||
|
sb.append(" ")
|
||||||
|
sb.appendFlags(flags, PROPERTY_FLAGS_MAP)
|
||||||
|
sb.append(if (Flags.Property.IS_VAR(flags)) "var " else "val ")
|
||||||
|
if (typeParams.isNotEmpty()) {
|
||||||
|
typeParams.joinTo(sb, prefix = "<", postfix = ">")
|
||||||
|
sb.append(" ")
|
||||||
|
}
|
||||||
|
if (receiverParameterType != null) {
|
||||||
|
sb.append(receiverParameterType).append(".")
|
||||||
|
}
|
||||||
|
sb.append(name)
|
||||||
|
if (returnType != null) {
|
||||||
|
sb.append(": ").append(returnType)
|
||||||
|
}
|
||||||
|
if (Flags.Property.HAS_CONSTANT(flags)) {
|
||||||
|
sb.append(" /* = ... */")
|
||||||
|
}
|
||||||
|
sb.appendln()
|
||||||
|
if (Flags.Property.HAS_GETTER(flags)) {
|
||||||
|
sb.append(" ")
|
||||||
|
sb.appendFlags(getterFlags, PROPERTY_ACCESSOR_FLAGS_MAP)
|
||||||
|
sb.appendln("get")
|
||||||
|
}
|
||||||
|
if (Flags.Property.HAS_SETTER(flags)) {
|
||||||
|
sb.append(" ")
|
||||||
|
sb.appendFlags(setterFlags, PROPERTY_ACCESSOR_FLAGS_MAP)
|
||||||
|
sb.append("set")
|
||||||
|
if (setterParameter != null) {
|
||||||
|
sb.append("(").append(setterParameter).append(")")
|
||||||
|
}
|
||||||
|
sb.appendln()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun visitConstructor(sb: StringBuilder, flags: Int): KmConstructorVisitor =
|
||||||
|
object : KmConstructorVisitor() {
|
||||||
|
val params = mutableListOf<String>()
|
||||||
|
var versionRequirement: String? = null
|
||||||
|
var jvmDesc: String? = null
|
||||||
|
|
||||||
|
override fun visitValueParameter(flags: Int, name: String): KmValueParameterVisitor? =
|
||||||
|
printValueParameter(flags, name) { params.add(it) }
|
||||||
|
|
||||||
|
override fun visitVersionRequirement(): KmVersionRequirementVisitor? =
|
||||||
|
printVersionRequirement { versionRequirement = it }
|
||||||
|
|
||||||
|
override fun visitExtensions(type: KmExtensionType): KmConstructorExtensionVisitor? {
|
||||||
|
if (type != JvmConstructorExtensionVisitor.TYPE) return null
|
||||||
|
return object : JvmConstructorExtensionVisitor() {
|
||||||
|
override fun visit(desc: String?) {
|
||||||
|
jvmDesc = desc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitEnd() {
|
||||||
|
sb.appendln()
|
||||||
|
if (versionRequirement != null) {
|
||||||
|
sb.appendln(" // $versionRequirement")
|
||||||
|
}
|
||||||
|
if (jvmDesc != null) {
|
||||||
|
sb.appendln(" // signature: $jvmDesc")
|
||||||
|
}
|
||||||
|
sb.append(" ")
|
||||||
|
sb.appendFlags(flags, CONSTRUCTOR_FLAGS_MAP)
|
||||||
|
sb.append("constructor(")
|
||||||
|
params.joinTo(sb)
|
||||||
|
sb.appendln(")")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun visitTypeAlias(sb: StringBuilder, flags: Int, name: String): KmTypeAliasVisitor =
|
||||||
|
object : KmTypeAliasVisitor() {
|
||||||
|
val annotations = mutableListOf<KmAnnotation>()
|
||||||
|
val typeParams = mutableListOf<String>()
|
||||||
|
var underlyingType: String? = null
|
||||||
|
var expandedType: String? = null
|
||||||
|
var versionRequirement: String? = null
|
||||||
|
|
||||||
|
override fun visitTypeParameter(flags: Int, name: String, id: Int, variance: KmVariance): KmTypeParameterVisitor? =
|
||||||
|
printTypeParameter(flags, name, id, variance) { typeParams.add(it) }
|
||||||
|
|
||||||
|
override fun visitUnderlyingType(flags: Int): KmTypeVisitor? =
|
||||||
|
printType(flags) { underlyingType = it }
|
||||||
|
|
||||||
|
override fun visitExpandedType(flags: Int): KmTypeVisitor? =
|
||||||
|
printType(flags) { expandedType = it }
|
||||||
|
|
||||||
|
override fun visitAnnotation(annotation: KmAnnotation) {
|
||||||
|
annotations += annotation
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitVersionRequirement(): KmVersionRequirementVisitor? =
|
||||||
|
printVersionRequirement { versionRequirement = it }
|
||||||
|
|
||||||
|
override fun visitEnd() {
|
||||||
|
sb.appendln()
|
||||||
|
if (versionRequirement != null) {
|
||||||
|
sb.appendln(" // $versionRequirement")
|
||||||
|
}
|
||||||
|
for (annotation in annotations) {
|
||||||
|
sb.append(" ").append("@").append(renderAnnotation(annotation)).appendln()
|
||||||
|
}
|
||||||
|
sb.append(" ")
|
||||||
|
sb.appendFlags(flags, VISIBILITY_FLAGS_MAP)
|
||||||
|
sb.append("typealias ").append(name)
|
||||||
|
if (typeParams.isNotEmpty()) {
|
||||||
|
typeParams.joinTo(sb, prefix = "<", postfix = ">")
|
||||||
|
}
|
||||||
|
if (underlyingType != null) {
|
||||||
|
sb.append(" = ").append(underlyingType)
|
||||||
|
}
|
||||||
|
if (expandedType != null) {
|
||||||
|
sb.append(" /* = ").append(expandedType).append(" */")
|
||||||
|
}
|
||||||
|
sb.appendln()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun printType(flags: Int, output: (String) -> Unit): KmTypeVisitor =
|
||||||
|
object : KmTypeVisitor() {
|
||||||
|
var classifier: String? = null
|
||||||
|
val arguments = mutableListOf<String>()
|
||||||
|
var abbreviatedType: String? = null
|
||||||
|
var outerType: String? = null
|
||||||
|
var platformTypeUpperBound: String? = null
|
||||||
|
var jvmIsRaw: Boolean? = null
|
||||||
|
var jvmAnnotations = mutableListOf<KmAnnotation>()
|
||||||
|
|
||||||
|
override fun visitClass(name: ClassName) {
|
||||||
|
classifier = name
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitTypeParameter(id: Int) {
|
||||||
|
classifier = "T#$id"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitTypeAlias(name: ClassName) {
|
||||||
|
classifier = "$name${SpecialCharacters.TYPE_ALIAS_MARKER}"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitAbbreviatedType(flags: Int): KmTypeVisitor? =
|
||||||
|
printType(flags) { abbreviatedType = it }
|
||||||
|
|
||||||
|
override fun visitArgument(flags: Int, variance: KmVariance): KmTypeVisitor? =
|
||||||
|
printType(flags) { argumentTypeString ->
|
||||||
|
arguments += buildString {
|
||||||
|
if (variance != KmVariance.INVARIANT) {
|
||||||
|
append(variance.name.toLowerCase()).append(" ")
|
||||||
|
}
|
||||||
|
append(argumentTypeString)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitStarProjection() {
|
||||||
|
arguments += "*"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitOuterType(flags: Int): KmTypeVisitor? =
|
||||||
|
printType(flags) { outerType = it }
|
||||||
|
|
||||||
|
override fun visitFlexibleTypeUpperBound(flags: Int, typeFlexibilityId: String?): KmTypeVisitor? =
|
||||||
|
if (typeFlexibilityId == JvmTypeExtensionVisitor.PLATFORM_TYPE_ID) {
|
||||||
|
printType(flags) { platformTypeUpperBound = it }
|
||||||
|
} else null
|
||||||
|
|
||||||
|
override fun visitExtensions(type: KmExtensionType): KmTypeExtensionVisitor? {
|
||||||
|
if (type != JvmTypeExtensionVisitor.TYPE) return null
|
||||||
|
return object : JvmTypeExtensionVisitor() {
|
||||||
|
override fun visit(isRaw: Boolean) {
|
||||||
|
jvmIsRaw = isRaw
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitAnnotation(annotation: KmAnnotation) {
|
||||||
|
jvmAnnotations.add(annotation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitEnd() {
|
||||||
|
output(buildString {
|
||||||
|
for (annotation in jvmAnnotations) {
|
||||||
|
append("@").append(renderAnnotation(annotation)).append(" ")
|
||||||
|
}
|
||||||
|
if (jvmIsRaw == true) {
|
||||||
|
append("/* raw */ ")
|
||||||
|
}
|
||||||
|
appendFlags(flags, TYPE_FLAGS_MAP)
|
||||||
|
if (outerType != null) {
|
||||||
|
append(outerType).append(".").append(classifier?.substringAfterLast('.'))
|
||||||
|
} else {
|
||||||
|
append(classifier)
|
||||||
|
}
|
||||||
|
if (arguments.isNotEmpty()) {
|
||||||
|
arguments.joinTo(this, prefix = "<", postfix = ">")
|
||||||
|
}
|
||||||
|
if (Flags.Type.IS_NULLABLE(flags)) {
|
||||||
|
append("?")
|
||||||
|
}
|
||||||
|
if (abbreviatedType != null) {
|
||||||
|
append(" /* = ").append(abbreviatedType).append(" */")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (platformTypeUpperBound == "$this?") {
|
||||||
|
append("!")
|
||||||
|
} else if (platformTypeUpperBound != null) {
|
||||||
|
append("..").append(platformTypeUpperBound)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun printTypeParameter(flags: Int, name: String, id: Int, variance: KmVariance, output: (String) -> Unit): KmTypeParameterVisitor =
|
||||||
|
object : KmTypeParameterVisitor() {
|
||||||
|
val bounds = mutableListOf<String>()
|
||||||
|
val jvmAnnotations = mutableListOf<KmAnnotation>()
|
||||||
|
|
||||||
|
override fun visitUpperBound(flags: Int): KmTypeVisitor? =
|
||||||
|
printType(flags) { bounds += it }
|
||||||
|
|
||||||
|
override fun visitExtensions(type: KmExtensionType): KmTypeParameterExtensionVisitor? {
|
||||||
|
if (type != JvmTypeParameterExtensionVisitor.TYPE) return null
|
||||||
|
return object : JvmTypeParameterExtensionVisitor() {
|
||||||
|
override fun visitAnnotation(annotation: KmAnnotation) {
|
||||||
|
jvmAnnotations.add(annotation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitEnd() {
|
||||||
|
output(buildString {
|
||||||
|
appendFlags(flags, TYPE_PARAMETER_FLAGS_MAP)
|
||||||
|
for (annotation in jvmAnnotations) {
|
||||||
|
append("@").append(renderAnnotation(annotation)).append(" ")
|
||||||
|
}
|
||||||
|
if (variance != KmVariance.INVARIANT) {
|
||||||
|
append(variance.name.toLowerCase()).append(" ")
|
||||||
|
}
|
||||||
|
append("T#$id /* $name */")
|
||||||
|
if (bounds.isNotEmpty()) {
|
||||||
|
bounds.joinTo(this, separator = " & ", prefix = " : ")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun printValueParameter(flags: Int, name: String, output: (String) -> Unit): KmValueParameterVisitor =
|
||||||
|
object : KmValueParameterVisitor() {
|
||||||
|
var varargElementType: String? = null
|
||||||
|
var type: String? = null
|
||||||
|
|
||||||
|
override fun visitType(flags: Int): KmTypeVisitor? =
|
||||||
|
printType(flags) { type = it }
|
||||||
|
|
||||||
|
override fun visitVarargElementType(flags: Int): KmTypeVisitor? =
|
||||||
|
printType(flags) { varargElementType = it }
|
||||||
|
|
||||||
|
override fun visitEnd() {
|
||||||
|
output(buildString {
|
||||||
|
appendFlags(flags, VALUE_PARAMETER_FLAGS_MAP)
|
||||||
|
if (varargElementType != null) {
|
||||||
|
append("vararg ").append(name).append(": ").append(varargElementType).append(" /* ").append(type).append(" */")
|
||||||
|
} else {
|
||||||
|
append(name).append(": ").append(type)
|
||||||
|
}
|
||||||
|
if (Flags.ValueParameter.DECLARES_DEFAULT_VALUE(flags)) {
|
||||||
|
append(" /* = ... */")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun renderAnnotation(annotation: KmAnnotation): String =
|
||||||
|
annotation.className + if (annotation.arguments.isEmpty()) "" else
|
||||||
|
annotation.arguments.entries.joinToString(prefix = "(", postfix = ")") { (name, argument) ->
|
||||||
|
"$name = ${renderAnnotationArgument(argument)}"
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun renderAnnotationArgument(arg: KmAnnotationArgument<*>): String =
|
||||||
|
when (arg) {
|
||||||
|
is KmAnnotationArgument.ByteValue -> arg.value.toString() + ".toByte()"
|
||||||
|
is KmAnnotationArgument.CharValue -> "'${arg.value.toString().sanitize(quote = '\'')}'"
|
||||||
|
is KmAnnotationArgument.ShortValue -> arg.value.toString() + ".toShort()"
|
||||||
|
is KmAnnotationArgument.IntValue -> arg.value.toString()
|
||||||
|
is KmAnnotationArgument.LongValue -> arg.value.toString() + "L"
|
||||||
|
is KmAnnotationArgument.FloatValue -> arg.value.toString() + "f"
|
||||||
|
is KmAnnotationArgument.DoubleValue -> arg.value.toString()
|
||||||
|
is KmAnnotationArgument.BooleanValue -> arg.value.toString()
|
||||||
|
is KmAnnotationArgument.StringValue -> "\"${arg.value.sanitize(quote = '"')}\""
|
||||||
|
is KmAnnotationArgument.KClassValue -> "${arg.value}::class"
|
||||||
|
is KmAnnotationArgument.EnumValue -> arg.value
|
||||||
|
is KmAnnotationArgument.AnnotationValue -> arg.value.let { annotation ->
|
||||||
|
val args = annotation.arguments.entries.joinToString { (name, argument) ->
|
||||||
|
"$name = ${renderAnnotationArgument(argument)}"
|
||||||
|
}
|
||||||
|
"${annotation.className}($args)"
|
||||||
|
}
|
||||||
|
is KmAnnotationArgument.ArrayValue -> arg.value.joinToString(prefix = "[", postfix = "]", transform = ::renderAnnotationArgument)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun String.sanitize(quote: Char): String =
|
||||||
|
buildString(length) {
|
||||||
|
for (c in this@sanitize) {
|
||||||
|
when (c) {
|
||||||
|
'\n' -> append("\\n")
|
||||||
|
'\r' -> append("\\r")
|
||||||
|
'\t' -> append("\\t")
|
||||||
|
quote -> append("\\").append(quote)
|
||||||
|
else -> append(if (c.isISOControl()) "\\u%04x".format(c.toInt()) else c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun printVersionRequirement(output: (String) -> Unit): KmVersionRequirementVisitor =
|
||||||
|
object : KmVersionRequirementVisitor() {
|
||||||
|
var kind: KmVersionRequirementVersionKind? = null
|
||||||
|
var level: KmVersionRequirementLevel? = null
|
||||||
|
var errorCode: Int? = null
|
||||||
|
var message: String? = null
|
||||||
|
var version: String? = null
|
||||||
|
|
||||||
|
override fun visit(kind: KmVersionRequirementVersionKind, level: KmVersionRequirementLevel, errorCode: Int?, message: String?) {
|
||||||
|
this.kind = kind
|
||||||
|
this.level = level
|
||||||
|
this.errorCode = errorCode
|
||||||
|
this.message = message
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitVersion(major: Int, minor: Int, patch: Int) {
|
||||||
|
version = "$major.$minor.$patch"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitEnd() {
|
||||||
|
output(buildString {
|
||||||
|
append("requires ").append(
|
||||||
|
when (kind!!) {
|
||||||
|
KmVersionRequirementVersionKind.LANGUAGE_VERSION -> "language version"
|
||||||
|
KmVersionRequirementVersionKind.COMPILER_VERSION -> "compiler version"
|
||||||
|
KmVersionRequirementVersionKind.API_VERSION -> "API version"
|
||||||
|
}
|
||||||
|
).append(" ").append(version)
|
||||||
|
|
||||||
|
listOfNotNull(
|
||||||
|
"level=$level",
|
||||||
|
errorCode?.let { "errorCode=$it" },
|
||||||
|
message?.let { "message=\"$it\"" }
|
||||||
|
).joinTo(this, prefix = " (", postfix = ")")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun StringBuilder.appendFlags(flags: Int, map: Map<MetadataFlag, String>) {
|
||||||
|
for ((modifier, string) in map) {
|
||||||
|
if (modifier(flags)) {
|
||||||
|
append(string)
|
||||||
|
if (string.isNotEmpty()) append(" ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AbstractPrinter<in T : KotlinClassMetadata> {
|
||||||
|
fun print(klass: T): String
|
||||||
|
}
|
||||||
|
|
||||||
|
class ClassPrinter : KmClassVisitor(), AbstractPrinter<KotlinClassMetadata.Class> {
|
||||||
|
private val sb = StringBuilder()
|
||||||
|
private val result = StringBuilder()
|
||||||
|
|
||||||
|
private var flags: Int? = null
|
||||||
|
private var name: ClassName? = null
|
||||||
|
private val typeParams = mutableListOf<String>()
|
||||||
|
private val supertypes = mutableListOf<String>()
|
||||||
|
private var versionRequirement: String? = null
|
||||||
|
|
||||||
|
override fun visit(flags: Int, name: ClassName) {
|
||||||
|
this.flags = flags
|
||||||
|
this.name = name
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitEnd() {
|
||||||
|
if (versionRequirement != null) {
|
||||||
|
result.appendln(" // $versionRequirement")
|
||||||
|
}
|
||||||
|
result.appendFlags(flags!!, CLASS_FLAGS_MAP)
|
||||||
|
result.append(name)
|
||||||
|
if (typeParams.isNotEmpty()) {
|
||||||
|
typeParams.joinTo(result, prefix = "<", postfix = ">")
|
||||||
|
}
|
||||||
|
if (supertypes.isNotEmpty()) {
|
||||||
|
result.append(" : ")
|
||||||
|
supertypes.joinTo(result)
|
||||||
|
}
|
||||||
|
result.appendln(" {")
|
||||||
|
result.append(sb)
|
||||||
|
result.appendln("}")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitTypeParameter(flags: Int, name: String, id: Int, variance: KmVariance): KmTypeParameterVisitor? =
|
||||||
|
printTypeParameter(flags, name, id, variance) { typeParams.add(it) }
|
||||||
|
|
||||||
|
override fun visitSupertype(flags: Int): KmTypeVisitor? =
|
||||||
|
printType(flags) { supertypes.add(it) }
|
||||||
|
|
||||||
|
override fun visitConstructor(flags: Int): KmConstructorVisitor? =
|
||||||
|
visitConstructor(sb, flags)
|
||||||
|
|
||||||
|
override fun visitFunction(flags: Int, name: String): KmFunctionVisitor? =
|
||||||
|
visitFunction(sb, flags, name)
|
||||||
|
|
||||||
|
override fun visitProperty(flags: Int, name: String, getterFlags: Int, setterFlags: Int): KmPropertyVisitor? =
|
||||||
|
visitProperty(sb, flags, name, getterFlags, setterFlags)
|
||||||
|
|
||||||
|
override fun visitTypeAlias(flags: Int, name: String): KmTypeAliasVisitor? =
|
||||||
|
visitTypeAlias(sb, flags, name)
|
||||||
|
|
||||||
|
override fun visitCompanionObject(name: String) {
|
||||||
|
sb.appendln()
|
||||||
|
sb.appendln(" // companion object: $name")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitNestedClass(name: String) {
|
||||||
|
sb.appendln()
|
||||||
|
sb.appendln(" // nested class: $name")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitEnumEntry(name: String) {
|
||||||
|
sb.appendln()
|
||||||
|
sb.appendln(" $name,")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitSealedSubclass(name: ClassName) {
|
||||||
|
sb.appendln()
|
||||||
|
sb.appendln(" // sealed subclass: $name")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitVersionRequirement(): KmVersionRequirementVisitor? =
|
||||||
|
printVersionRequirement { versionRequirement = it }
|
||||||
|
|
||||||
|
override fun print(klass: KotlinClassMetadata.Class): String {
|
||||||
|
klass.accept(this)
|
||||||
|
return result.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class PackagePrinter : KmPackageVisitor() {
|
||||||
|
internal val sb = StringBuilder().apply {
|
||||||
|
appendln("package {")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitEnd() {
|
||||||
|
sb.appendln("}")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitFunction(flags: Int, name: String): KmFunctionVisitor? =
|
||||||
|
visitFunction(sb, flags, name)
|
||||||
|
|
||||||
|
override fun visitProperty(flags: Int, name: String, getterFlags: Int, setterFlags: Int): KmPropertyVisitor? =
|
||||||
|
visitProperty(sb, flags, name, getterFlags, setterFlags)
|
||||||
|
|
||||||
|
override fun visitTypeAlias(flags: Int, name: String): KmTypeAliasVisitor? =
|
||||||
|
visitTypeAlias(sb, flags, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
class FileFacadePrinter : PackagePrinter(), AbstractPrinter<KotlinClassMetadata.FileFacade> {
|
||||||
|
override fun print(klass: KotlinClassMetadata.FileFacade): String {
|
||||||
|
klass.accept(this)
|
||||||
|
return sb.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LambdaPrinter : KmLambdaVisitor(), AbstractPrinter<KotlinClassMetadata.SyntheticClass> {
|
||||||
|
private val sb = StringBuilder().apply {
|
||||||
|
appendln("lambda {")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitFunction(flags: Int, name: String): KmFunctionVisitor? =
|
||||||
|
visitFunction(sb, flags, name)
|
||||||
|
|
||||||
|
override fun visitEnd() {
|
||||||
|
sb.appendln("}")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun print(klass: KotlinClassMetadata.SyntheticClass): String {
|
||||||
|
klass.accept(this)
|
||||||
|
return sb.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MultiFileClassPartPrinter : PackagePrinter(), AbstractPrinter<KotlinClassMetadata.MultiFileClassPart> {
|
||||||
|
override fun print(klass: KotlinClassMetadata.MultiFileClassPart): String {
|
||||||
|
sb.appendln(" // facade: ${klass.facadeClassName}")
|
||||||
|
klass.accept(this)
|
||||||
|
return sb.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MultiFileClassFacadePrinter : AbstractPrinter<KotlinClassMetadata.MultiFileClassFacade> {
|
||||||
|
override fun print(klass: KotlinClassMetadata.MultiFileClassFacade): String =
|
||||||
|
buildString {
|
||||||
|
appendln("multi-file class {")
|
||||||
|
for (part in klass.partClassNames) {
|
||||||
|
appendln(" // $part")
|
||||||
|
}
|
||||||
|
appendln("}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val VISIBILITY_FLAGS_MAP = mapOf(
|
||||||
|
Flags.IS_INTERNAL to "internal",
|
||||||
|
Flags.IS_PRIVATE to "private",
|
||||||
|
Flags.IS_PRIVATE_TO_THIS to "private",
|
||||||
|
Flags.IS_PROTECTED to "protected",
|
||||||
|
Flags.IS_PUBLIC to "public",
|
||||||
|
Flags.IS_LOCAL to "local"
|
||||||
|
)
|
||||||
|
|
||||||
|
private val COMMON_FLAGS_MAP = VISIBILITY_FLAGS_MAP + mapOf(
|
||||||
|
Flags.IS_FINAL to "final",
|
||||||
|
Flags.IS_OPEN to "open",
|
||||||
|
Flags.IS_ABSTRACT to "abstract",
|
||||||
|
Flags.IS_SEALED to "sealed"
|
||||||
|
)
|
||||||
|
|
||||||
|
private val CLASS_FLAGS_MAP = COMMON_FLAGS_MAP + mapOf(
|
||||||
|
Flags.Class.IS_INNER to "inner",
|
||||||
|
Flags.Class.IS_DATA to "data",
|
||||||
|
Flags.Class.IS_EXTERNAL to "external",
|
||||||
|
Flags.Class.IS_EXPECT to "expect",
|
||||||
|
Flags.Class.IS_INLINE to "inline",
|
||||||
|
|
||||||
|
Flags.Class.IS_CLASS to "class",
|
||||||
|
Flags.Class.IS_INTERFACE to "interface",
|
||||||
|
Flags.Class.IS_ENUM_CLASS to "enum class",
|
||||||
|
Flags.Class.IS_ENUM_ENTRY to "enum entry",
|
||||||
|
Flags.Class.IS_ANNOTATION_CLASS to "annotation class",
|
||||||
|
Flags.Class.IS_OBJECT to "object",
|
||||||
|
Flags.Class.IS_COMPANION_OBJECT to "companion object"
|
||||||
|
)
|
||||||
|
|
||||||
|
private val CONSTRUCTOR_FLAGS_MAP = VISIBILITY_FLAGS_MAP + mapOf(
|
||||||
|
Flags.Constructor.IS_PRIMARY to "/* primary */"
|
||||||
|
)
|
||||||
|
|
||||||
|
private val FUNCTION_FLAGS_MAP = COMMON_FLAGS_MAP + mapOf(
|
||||||
|
Flags.Function.IS_DECLARATION to "",
|
||||||
|
Flags.Function.IS_FAKE_OVERRIDE to "/* fake override */",
|
||||||
|
Flags.Function.IS_DELEGATION to "/* delegation */",
|
||||||
|
Flags.Function.IS_SYNTHESIZED to "/* synthesized */",
|
||||||
|
|
||||||
|
Flags.Function.IS_OPERATOR to "operator",
|
||||||
|
Flags.Function.IS_INFIX to "infix",
|
||||||
|
Flags.Function.IS_INLINE to "inline",
|
||||||
|
Flags.Function.IS_TAILREC to "tailrec",
|
||||||
|
Flags.Function.IS_EXTERNAL to "external",
|
||||||
|
Flags.Function.IS_SUSPEND to "suspend",
|
||||||
|
Flags.Function.IS_EXPECT to "expect"
|
||||||
|
)
|
||||||
|
|
||||||
|
private val PROPERTY_FLAGS_MAP = COMMON_FLAGS_MAP + mapOf(
|
||||||
|
Flags.Property.IS_DECLARATION to "",
|
||||||
|
Flags.Property.IS_FAKE_OVERRIDE to "/* fake override */",
|
||||||
|
Flags.Property.IS_DELEGATION to "/* delegation */",
|
||||||
|
Flags.Property.IS_SYNTHESIZED to "/* synthesized */",
|
||||||
|
|
||||||
|
Flags.Property.IS_CONST to "const",
|
||||||
|
Flags.Property.IS_LATEINIT to "lateinit",
|
||||||
|
Flags.Property.IS_EXTERNAL to "external",
|
||||||
|
Flags.Property.IS_DELEGATED to "/* delegated */",
|
||||||
|
Flags.Property.IS_EXPECT to "expect"
|
||||||
|
)
|
||||||
|
|
||||||
|
private val PROPERTY_ACCESSOR_FLAGS_MAP = COMMON_FLAGS_MAP + mapOf(
|
||||||
|
Flags.PropertyAccessor.IS_NOT_DEFAULT to "/* non-default */",
|
||||||
|
Flags.PropertyAccessor.IS_EXTERNAL to "external",
|
||||||
|
Flags.PropertyAccessor.IS_INLINE to "inline"
|
||||||
|
)
|
||||||
|
|
||||||
|
private val VALUE_PARAMETER_FLAGS_MAP = mapOf(
|
||||||
|
Flags.ValueParameter.IS_CROSSINLINE to "crossinline",
|
||||||
|
Flags.ValueParameter.IS_NOINLINE to "noinline"
|
||||||
|
)
|
||||||
|
|
||||||
|
private val TYPE_PARAMETER_FLAGS_MAP = mapOf(
|
||||||
|
Flags.TypeParameter.IS_REIFIED to "reified"
|
||||||
|
)
|
||||||
|
|
||||||
|
private val TYPE_FLAGS_MAP = mapOf(
|
||||||
|
Flags.Type.IS_SUSPEND to "suspend"
|
||||||
|
)
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.kotlinp
|
||||||
|
|
||||||
|
import kotlinx.metadata.jvm.KotlinClassHeader
|
||||||
|
import org.objectweb.asm.AnnotationVisitor
|
||||||
|
import org.objectweb.asm.ClassReader
|
||||||
|
import org.objectweb.asm.ClassVisitor
|
||||||
|
import org.objectweb.asm.Opcodes
|
||||||
|
import java.io.File
|
||||||
|
import java.io.FileInputStream
|
||||||
|
|
||||||
|
internal fun File.readKotlinClassHeader(): KotlinClassHeader? {
|
||||||
|
var header: KotlinClassHeader? = null
|
||||||
|
|
||||||
|
try {
|
||||||
|
ClassReader(FileInputStream(this)).accept(object : ClassVisitor(Opcodes.ASM4) {
|
||||||
|
override fun visitAnnotation(desc: String, visible: Boolean): AnnotationVisitor? =
|
||||||
|
if (desc == "Lkotlin/Metadata;") readMetadataVisitor { header = it }
|
||||||
|
else null
|
||||||
|
}, ClassReader.SKIP_CODE or ClassReader.SKIP_DEBUG or ClassReader.SKIP_FRAMES)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return header
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||||
|
private fun readMetadataVisitor(output: (KotlinClassHeader) -> Unit): AnnotationVisitor =
|
||||||
|
object : AnnotationVisitor(Opcodes.ASM4) {
|
||||||
|
var kind: Int? = null
|
||||||
|
var metadataVersion: IntArray? = null
|
||||||
|
var bytecodeVersion: IntArray? = null
|
||||||
|
var data1: Array<String>? = null
|
||||||
|
var data2: Array<String>? = null
|
||||||
|
var extraString: String? = null
|
||||||
|
var packageName: String? = null
|
||||||
|
var extraInt: Int? = null
|
||||||
|
|
||||||
|
override fun visit(name: String?, value: Any?) {
|
||||||
|
when (name) {
|
||||||
|
Metadata::k.name -> kind = value as? Int
|
||||||
|
Metadata::mv.name -> metadataVersion = value as? IntArray
|
||||||
|
Metadata::bv.name -> bytecodeVersion = value as? IntArray
|
||||||
|
Metadata::xs.name -> extraString = value as? String
|
||||||
|
Metadata::xi.name -> extraInt = value as? Int
|
||||||
|
Metadata::pn.name -> packageName = value as? String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitArray(name: String?): AnnotationVisitor? =
|
||||||
|
when (name) {
|
||||||
|
Metadata::d1.name -> stringArrayVisitor { data1 = it }
|
||||||
|
Metadata::d2.name -> stringArrayVisitor { data2 = it }
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun stringArrayVisitor(output: (Array<String>) -> Unit): AnnotationVisitor {
|
||||||
|
return object : AnnotationVisitor(Opcodes.ASM4) {
|
||||||
|
val strings = mutableListOf<String>()
|
||||||
|
|
||||||
|
override fun visit(name: String?, value: Any?) {
|
||||||
|
(value as? String)?.let(strings::add)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitEnd() {
|
||||||
|
output(strings.toTypedArray())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitEnd() {
|
||||||
|
output(KotlinClassHeader(kind, metadataVersion, bytecodeVersion, data1, data2, extraString, packageName, extraInt))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.kotlinp.test
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.test.TestCaseWithTmpdir
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
abstract class AbstractKotlinpTest : TestCaseWithTmpdir() {
|
||||||
|
protected fun doTest(fileName: String) {
|
||||||
|
compileAndPrintAllFiles(File(fileName), testRootDisposable, tmpdir, compareWithTxt = true)
|
||||||
|
}
|
||||||
|
}
|
||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.kotlinp.test
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.generators.tests.generator.testGroup
|
||||||
|
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
System.setProperty("java.awt.headless", "true")
|
||||||
|
|
||||||
|
testGroup("libraries/tools/kotlinp/test", "libraries/tools/kotlinp/testData") {
|
||||||
|
testClass<AbstractKotlinpTest> {
|
||||||
|
model("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+86
@@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.kotlinp.test;
|
||||||
|
|
||||||
|
import com.intellij.testFramework.TestDataPath;
|
||||||
|
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
|
||||||
|
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||||
|
import org.jetbrains.kotlin.test.TargetBackend;
|
||||||
|
import org.jetbrains.kotlin.test.TestMetadata;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
@TestMetadata("libraries/tools/kotlinp/testData")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public class KotlinpTestGenerated extends AbstractKotlinpTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInTestData() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("libraries/tools/kotlinp/testData"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("Annotations.kt")
|
||||||
|
public void testAnnotations() throws Exception {
|
||||||
|
runTest("libraries/tools/kotlinp/testData/Annotations.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("Lambda.kt")
|
||||||
|
public void testLambda() throws Exception {
|
||||||
|
runTest("libraries/tools/kotlinp/testData/Lambda.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("LocalClass.kt")
|
||||||
|
public void testLocalClass() throws Exception {
|
||||||
|
runTest("libraries/tools/kotlinp/testData/LocalClass.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("MultiFileClass.kt")
|
||||||
|
public void testMultiFileClass() throws Exception {
|
||||||
|
runTest("libraries/tools/kotlinp/testData/MultiFileClass.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("NestedClasses.kt")
|
||||||
|
public void testNestedClasses() throws Exception {
|
||||||
|
runTest("libraries/tools/kotlinp/testData/NestedClasses.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("PlatformType.kt")
|
||||||
|
public void testPlatformType() throws Exception {
|
||||||
|
runTest("libraries/tools/kotlinp/testData/PlatformType.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("SimpleClass.kt")
|
||||||
|
public void testSimpleClass() throws Exception {
|
||||||
|
runTest("libraries/tools/kotlinp/testData/SimpleClass.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("SimplePackage.kt")
|
||||||
|
public void testSimplePackage() throws Exception {
|
||||||
|
runTest("libraries/tools/kotlinp/testData/SimplePackage.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("SyntheticClass.kt")
|
||||||
|
public void testSyntheticClass() throws Exception {
|
||||||
|
runTest("libraries/tools/kotlinp/testData/SyntheticClass.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("TypeParameters.kt")
|
||||||
|
public void testTypeParameters() throws Exception {
|
||||||
|
runTest("libraries/tools/kotlinp/testData/TypeParameters.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("VersionRequirement.kt")
|
||||||
|
public void testVersionRequirement() throws Exception {
|
||||||
|
runTest("libraries/tools/kotlinp/testData/VersionRequirement.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.kotlinp.test
|
||||||
|
|
||||||
|
import com.intellij.openapi.Disposable
|
||||||
|
import org.jetbrains.kotlin.checkers.setupLanguageVersionSettingsForCompilerTests
|
||||||
|
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
||||||
|
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||||
|
import org.jetbrains.kotlin.codegen.GenerationUtils
|
||||||
|
import org.jetbrains.kotlin.kotlinp.Kotlinp
|
||||||
|
import org.jetbrains.kotlin.test.ConfigurationKind
|
||||||
|
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||||
|
import org.jetbrains.kotlin.test.TestJdkKind
|
||||||
|
import java.io.File
|
||||||
|
import kotlin.test.fail
|
||||||
|
|
||||||
|
fun compileAndPrintAllFiles(file: File, disposable: Disposable, tmpdir: File, compareWithTxt: Boolean) {
|
||||||
|
val sb = StringBuilder()
|
||||||
|
|
||||||
|
compile(file, disposable, tmpdir) { outputFile ->
|
||||||
|
when (outputFile.extension) {
|
||||||
|
"kotlin_module" -> {
|
||||||
|
// TODO: support kotlin_module files
|
||||||
|
}
|
||||||
|
"class" -> {
|
||||||
|
sb.appendFileName(outputFile.relativeTo(tmpdir))
|
||||||
|
sb.append(Kotlinp.renderClassFile(Kotlinp.readClassFile(outputFile)!!))
|
||||||
|
}
|
||||||
|
else -> fail("Unknown file: $outputFile")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (compareWithTxt) {
|
||||||
|
KotlinTestUtils.assertEqualsToFile(File(file.path.replace(".kt", ".txt")), sb.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun compile(file: File, disposable: Disposable, tmpdir: File, forEachOutputFile: (File) -> Unit) {
|
||||||
|
val environment = KotlinCoreEnvironment.createForTests(
|
||||||
|
disposable,
|
||||||
|
KotlinTestUtils.newConfiguration(ConfigurationKind.ALL, TestJdkKind.MOCK_JDK),
|
||||||
|
EnvironmentConfigFiles.JVM_CONFIG_FILES
|
||||||
|
)
|
||||||
|
setupLanguageVersionSettingsForCompilerTests(file.readText(), environment)
|
||||||
|
val ktFile = KotlinTestUtils.createFile(file.name, file.readText(), environment.project)
|
||||||
|
GenerationUtils.compileFileTo(ktFile, environment, tmpdir)
|
||||||
|
|
||||||
|
for (outputFile in tmpdir.walkTopDown().sortedBy { it.nameWithoutExtension }) {
|
||||||
|
if (outputFile.isFile) {
|
||||||
|
forEachOutputFile(outputFile)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun StringBuilder.appendFileName(file: File) {
|
||||||
|
appendln("// $file")
|
||||||
|
appendln("// ------------------------------------------")
|
||||||
|
}
|
||||||
+52
@@ -0,0 +1,52 @@
|
|||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
@Target(AnnotationTarget.TYPE)
|
||||||
|
annotation class A(
|
||||||
|
val z: Boolean,
|
||||||
|
val c: Char,
|
||||||
|
val b: Byte,
|
||||||
|
val s: Short,
|
||||||
|
val i: Int,
|
||||||
|
val f: Float,
|
||||||
|
val j: Long,
|
||||||
|
val d: Double,
|
||||||
|
val za: BooleanArray,
|
||||||
|
val ca: CharArray,
|
||||||
|
val ba: ByteArray,
|
||||||
|
val sa: ShortArray,
|
||||||
|
val ia: IntArray,
|
||||||
|
val fa: FloatArray,
|
||||||
|
val ja: LongArray,
|
||||||
|
val da: DoubleArray,
|
||||||
|
val str: String,
|
||||||
|
val enum: AnnotationTarget,
|
||||||
|
val klass: KClass<*>,
|
||||||
|
val anno: B
|
||||||
|
)
|
||||||
|
|
||||||
|
annotation class B(val value: String)
|
||||||
|
|
||||||
|
class C {
|
||||||
|
fun typeAnnotation(): @A(
|
||||||
|
true,
|
||||||
|
'x',
|
||||||
|
1.toByte(),
|
||||||
|
42.toShort(),
|
||||||
|
42424242,
|
||||||
|
-2.72f,
|
||||||
|
239239239239239L,
|
||||||
|
3.14,
|
||||||
|
[true],
|
||||||
|
['\''],
|
||||||
|
[1.toByte()],
|
||||||
|
[42.toShort()],
|
||||||
|
[42424242],
|
||||||
|
[-2.72f],
|
||||||
|
[239239239239239L],
|
||||||
|
[3.14],
|
||||||
|
"aba\ncaba'\"\t\u0001\u0002\uA66E",
|
||||||
|
AnnotationTarget.CLASS,
|
||||||
|
C::class,
|
||||||
|
B(value = "aba\ncaba'\"\t\u0001\u0002\uA66E")
|
||||||
|
) Unit {}
|
||||||
|
}
|
||||||
+108
@@ -0,0 +1,108 @@
|
|||||||
|
// A.class
|
||||||
|
// ------------------------------------------
|
||||||
|
public final annotation class A : kotlin/Annotation {
|
||||||
|
|
||||||
|
// signature: <init>(ZCBSIFJD[Z[C[B[S[I[F[J[DLjava/lang/String;Lkotlin/annotation/AnnotationTarget;Lkotlin/reflect/KClass;LB;)V
|
||||||
|
public /* primary */ constructor(z: kotlin/Boolean, c: kotlin/Char, b: kotlin/Byte, s: kotlin/Short, i: kotlin/Int, f: kotlin/Float, j: kotlin/Long, d: kotlin/Double, za: kotlin/BooleanArray, ca: kotlin/CharArray, ba: kotlin/ByteArray, sa: kotlin/ShortArray, ia: kotlin/IntArray, fa: kotlin/FloatArray, ja: kotlin/LongArray, da: kotlin/DoubleArray, str: kotlin/String, enum: kotlin/annotation/AnnotationTarget, klass: kotlin/reflect/KClass<*>, anno: B)
|
||||||
|
|
||||||
|
// field: anno:LB;
|
||||||
|
public final val anno: B
|
||||||
|
public final get
|
||||||
|
|
||||||
|
// field: b:B
|
||||||
|
public final val b: kotlin/Byte
|
||||||
|
public final get
|
||||||
|
|
||||||
|
// field: ba:[B
|
||||||
|
public final val ba: kotlin/ByteArray
|
||||||
|
public final get
|
||||||
|
|
||||||
|
// field: c:C
|
||||||
|
public final val c: kotlin/Char
|
||||||
|
public final get
|
||||||
|
|
||||||
|
// field: ca:[C
|
||||||
|
public final val ca: kotlin/CharArray
|
||||||
|
public final get
|
||||||
|
|
||||||
|
// field: d:D
|
||||||
|
public final val d: kotlin/Double
|
||||||
|
public final get
|
||||||
|
|
||||||
|
// field: da:[D
|
||||||
|
public final val da: kotlin/DoubleArray
|
||||||
|
public final get
|
||||||
|
|
||||||
|
// field: enum:Lkotlin/annotation/AnnotationTarget;
|
||||||
|
public final val enum: kotlin/annotation/AnnotationTarget
|
||||||
|
public final get
|
||||||
|
|
||||||
|
// field: f:F
|
||||||
|
public final val f: kotlin/Float
|
||||||
|
public final get
|
||||||
|
|
||||||
|
// field: fa:[F
|
||||||
|
public final val fa: kotlin/FloatArray
|
||||||
|
public final get
|
||||||
|
|
||||||
|
// field: i:I
|
||||||
|
public final val i: kotlin/Int
|
||||||
|
public final get
|
||||||
|
|
||||||
|
// field: ia:[I
|
||||||
|
public final val ia: kotlin/IntArray
|
||||||
|
public final get
|
||||||
|
|
||||||
|
// field: j:J
|
||||||
|
public final val j: kotlin/Long
|
||||||
|
public final get
|
||||||
|
|
||||||
|
// field: ja:[J
|
||||||
|
public final val ja: kotlin/LongArray
|
||||||
|
public final get
|
||||||
|
|
||||||
|
// field: klass:Lkotlin/reflect/KClass;
|
||||||
|
public final val klass: kotlin/reflect/KClass<*>
|
||||||
|
public final get
|
||||||
|
|
||||||
|
// field: s:S
|
||||||
|
public final val s: kotlin/Short
|
||||||
|
public final get
|
||||||
|
|
||||||
|
// field: sa:[S
|
||||||
|
public final val sa: kotlin/ShortArray
|
||||||
|
public final get
|
||||||
|
|
||||||
|
// field: str:Ljava/lang/String;
|
||||||
|
public final val str: kotlin/String
|
||||||
|
public final get
|
||||||
|
|
||||||
|
// field: z:Z
|
||||||
|
public final val z: kotlin/Boolean
|
||||||
|
public final get
|
||||||
|
|
||||||
|
// field: za:[Z
|
||||||
|
public final val za: kotlin/BooleanArray
|
||||||
|
public final get
|
||||||
|
}
|
||||||
|
// B.class
|
||||||
|
// ------------------------------------------
|
||||||
|
public final annotation class B : kotlin/Annotation {
|
||||||
|
|
||||||
|
// signature: <init>(Ljava/lang/String;)V
|
||||||
|
public /* primary */ constructor(value: kotlin/String)
|
||||||
|
|
||||||
|
// field: value:Ljava/lang/String;
|
||||||
|
public final val value: kotlin/String
|
||||||
|
public final get
|
||||||
|
}
|
||||||
|
// C.class
|
||||||
|
// ------------------------------------------
|
||||||
|
public final class C : kotlin/Any {
|
||||||
|
|
||||||
|
// signature: <init>()V
|
||||||
|
public /* primary */ constructor()
|
||||||
|
|
||||||
|
// signature: typeAnnotation()V
|
||||||
|
public final fun typeAnnotation(): @A(z = true, c = 'x', b = 1.toByte(), s = 42.toShort(), i = 42424242, f = -2.72f, j = 239239239239239L, d = 3.14, za = [true], ca = ['\''], ba = [1.toByte()], sa = [42.toShort()], ia = [42424242], fa = [-2.72f], ja = [239239239239239L], da = [3.14], str = "aba\ncaba'\"\t\u0001\u0002ꙮ", enum = kotlin/annotation/AnnotationTarget.CLASS, klass = C::class, anno = B(value = "aba\ncaba'\"\t\u0001\u0002ꙮ")) kotlin/Unit
|
||||||
|
}
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
fun test() {
|
||||||
|
val f = {}
|
||||||
|
val g = fun Unit.(s: IntArray?, t: Set<Double>): String { return "" }
|
||||||
|
}
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
// LambdaKt.class
|
||||||
|
// ------------------------------------------
|
||||||
|
package {
|
||||||
|
|
||||||
|
// signature: test()V
|
||||||
|
public final fun test(): kotlin/Unit
|
||||||
|
}
|
||||||
|
// LambdaKt$test$f$1.class
|
||||||
|
// ------------------------------------------
|
||||||
|
lambda {
|
||||||
|
|
||||||
|
// signature: invoke()V
|
||||||
|
local final fun <anonymous>(): kotlin/Unit
|
||||||
|
}
|
||||||
|
// LambdaKt$test$g$1.class
|
||||||
|
// ------------------------------------------
|
||||||
|
lambda {
|
||||||
|
|
||||||
|
// signature: invoke(Lkotlin/Unit;[ILjava/util/Set;)Ljava/lang/String;
|
||||||
|
local final fun kotlin/Unit.<no name provided>(s: kotlin/IntArray?, t: kotlin/collections/Set<kotlin/Double>): kotlin/String
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
class A {
|
||||||
|
init {
|
||||||
|
class L<T> {
|
||||||
|
inner class I
|
||||||
|
|
||||||
|
fun x(l: L<I>) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
// A.class
|
||||||
|
// ------------------------------------------
|
||||||
|
public final class A : kotlin/Any {
|
||||||
|
|
||||||
|
// signature: <init>()V
|
||||||
|
public /* primary */ constructor()
|
||||||
|
}
|
||||||
|
// A$L.class
|
||||||
|
// ------------------------------------------
|
||||||
|
local final class .A$L<T#0 /* T */> : kotlin/Any {
|
||||||
|
|
||||||
|
// signature: <init>()V
|
||||||
|
public /* primary */ constructor()
|
||||||
|
|
||||||
|
// signature: x(LA$L;)V
|
||||||
|
public final fun x(l: .A$L<.A$L<T#0>.I>): kotlin/Unit
|
||||||
|
|
||||||
|
// nested class: I
|
||||||
|
}
|
||||||
|
// A$L$I.class
|
||||||
|
// ------------------------------------------
|
||||||
|
local final inner class .A$L.I : kotlin/Any {
|
||||||
|
|
||||||
|
// signature: <init>(LA$L;)V
|
||||||
|
public /* primary */ constructor()
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
@file:JvmMultifileClass
|
||||||
|
@file:JvmName("File")
|
||||||
|
package test
|
||||||
|
|
||||||
|
const val x = 42
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
// test/File.class
|
||||||
|
// ------------------------------------------
|
||||||
|
multi-file class {
|
||||||
|
// test/File__MultiFileClassKt
|
||||||
|
}
|
||||||
|
// test/File__MultiFileClassKt.class
|
||||||
|
// ------------------------------------------
|
||||||
|
package {
|
||||||
|
// facade: test/File
|
||||||
|
|
||||||
|
// field: x:I
|
||||||
|
public final const val x: kotlin/Int /* = ... */
|
||||||
|
public final get
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
interface A {
|
||||||
|
interface B {
|
||||||
|
interface C
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object D {
|
||||||
|
enum class E {
|
||||||
|
E1,
|
||||||
|
E2,
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class F {
|
||||||
|
class G : F()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
// A.class
|
||||||
|
// ------------------------------------------
|
||||||
|
public abstract interface A : kotlin/Any {
|
||||||
|
|
||||||
|
// companion object: D
|
||||||
|
|
||||||
|
// nested class: B
|
||||||
|
|
||||||
|
// nested class: D
|
||||||
|
}
|
||||||
|
// A$B.class
|
||||||
|
// ------------------------------------------
|
||||||
|
public abstract interface A.B : kotlin/Any {
|
||||||
|
|
||||||
|
// nested class: C
|
||||||
|
}
|
||||||
|
// A$B$C.class
|
||||||
|
// ------------------------------------------
|
||||||
|
public abstract interface A.B.C : kotlin/Any {
|
||||||
|
}
|
||||||
|
// A$D.class
|
||||||
|
// ------------------------------------------
|
||||||
|
public final companion object A.D : kotlin/Any {
|
||||||
|
|
||||||
|
// signature: <init>()V
|
||||||
|
private /* primary */ constructor()
|
||||||
|
|
||||||
|
// nested class: E
|
||||||
|
|
||||||
|
// nested class: F
|
||||||
|
}
|
||||||
|
// A$D$E.class
|
||||||
|
// ------------------------------------------
|
||||||
|
public final enum class A.D.E : kotlin/Enum<A.D.E> {
|
||||||
|
|
||||||
|
// signature: <init>(Ljava/lang/String;I)V
|
||||||
|
private /* primary */ constructor()
|
||||||
|
|
||||||
|
E1,
|
||||||
|
|
||||||
|
E2,
|
||||||
|
}
|
||||||
|
// A$D$F.class
|
||||||
|
// ------------------------------------------
|
||||||
|
public sealed class A.D.F : kotlin/Any {
|
||||||
|
|
||||||
|
// signature: <init>()V
|
||||||
|
private /* primary */ constructor()
|
||||||
|
|
||||||
|
// nested class: G
|
||||||
|
|
||||||
|
// sealed subclass: A.D.F.G
|
||||||
|
}
|
||||||
|
// A$D$F$G.class
|
||||||
|
// ------------------------------------------
|
||||||
|
public final class A.D.F.G : A.D.F {
|
||||||
|
|
||||||
|
// signature: <init>()V
|
||||||
|
public /* primary */ constructor()
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class PlatformType {
|
||||||
|
fun nullability() = File(".").absoluteFile
|
||||||
|
|
||||||
|
fun mutability() = File(".").toURI().toURL().openConnection().headerFields
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
// PlatformType.class
|
||||||
|
// ------------------------------------------
|
||||||
|
public final class PlatformType : kotlin/Any {
|
||||||
|
|
||||||
|
// signature: <init>()V
|
||||||
|
public /* primary */ constructor()
|
||||||
|
|
||||||
|
// signature: mutability()Ljava/util/Map;
|
||||||
|
public final fun mutability(): kotlin/collections/MutableMap<kotlin/String!, kotlin/collections/MutableList<kotlin/String!>..kotlin/collections/List<kotlin/String!>?>..kotlin/collections/Map<kotlin/String!, kotlin/collections/MutableList<kotlin/String!>..kotlin/collections/List<kotlin/String!>?>?
|
||||||
|
|
||||||
|
// signature: nullability()Ljava/io/File;
|
||||||
|
public final fun nullability(): java/io/File!
|
||||||
|
}
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
class SimpleClass<in A>(val p: Int = 42) {
|
||||||
|
constructor(s: Array<String?>?) : this(s?.size ?: 0)
|
||||||
|
|
||||||
|
var x: Long = p.toLong()
|
||||||
|
external get
|
||||||
|
@JvmName("SET_X") set
|
||||||
|
|
||||||
|
internal fun <U : A, V, A> A.f(vararg z: Map<V, U?>): Set<*> where V : A {
|
||||||
|
error("")
|
||||||
|
}
|
||||||
|
|
||||||
|
protected suspend inline fun <reified T> g(crossinline a: () -> A, noinline b: suspend () -> T) {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
// SimpleClass.class
|
||||||
|
// ------------------------------------------
|
||||||
|
public final class SimpleClass<in T#0 /* A */> : kotlin/Any {
|
||||||
|
|
||||||
|
// signature: <init>([Ljava/lang/String;)V
|
||||||
|
public constructor(s: kotlin/Array<kotlin/String?>?)
|
||||||
|
|
||||||
|
// signature: <init>(I)V
|
||||||
|
public /* primary */ constructor(p: kotlin/Int /* = ... */)
|
||||||
|
|
||||||
|
// requires language version 1.1.0 (level=ERROR)
|
||||||
|
// signature: g(Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
|
||||||
|
protected final inline suspend fun <reified T#1 /* T */> g(crossinline a: kotlin/Function0<T#0>, noinline b: suspend kotlin/Function1<kotlin/coroutines/experimental/Continuation<T#1>, kotlin/Any?>): kotlin/Unit
|
||||||
|
|
||||||
|
// signature: f$test_module(Ljava/lang/Object;[Ljava/util/Map;)Ljava/util/Set;
|
||||||
|
internal final fun <T#1 /* U */ : T#3, T#2 /* V */ : T#3, T#3 /* A */> T#3.f(vararg z: kotlin/collections/Map<T#2, T#1?> /* kotlin/Array<out kotlin/collections/Map<T#2, T#1?>> */): kotlin/collections/Set<*>
|
||||||
|
|
||||||
|
// field: p:I
|
||||||
|
// getter: getP()I
|
||||||
|
public final val p: kotlin/Int
|
||||||
|
public final get
|
||||||
|
|
||||||
|
// field: x:J
|
||||||
|
// getter: getX()J
|
||||||
|
// setter: SET_X(J)V
|
||||||
|
public final var x: kotlin/Long
|
||||||
|
public final /* non-default */ external get
|
||||||
|
public final /* non-default */ set(<set-?>: kotlin/Long)
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
internal inline fun <reified X : Any> topLevelFun(x: X) = X::class
|
||||||
|
|
||||||
|
var topLevelProp: String? = null
|
||||||
|
private set
|
||||||
|
|
||||||
|
typealias F<T, U> = Map<T, (StringBuilder) -> U?>
|
||||||
|
|
||||||
|
typealias G<S> = F<List<S>, Set<S>>
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
// SimplePackageKt.class
|
||||||
|
// ------------------------------------------
|
||||||
|
package {
|
||||||
|
|
||||||
|
// signature: topLevelFun(Ljava/lang/Object;)Lkotlin/reflect/KClass;
|
||||||
|
internal final inline fun <reified T#0 /* X */ : kotlin/Any> topLevelFun(x: T#0): kotlin/reflect/KClass<T#0>
|
||||||
|
|
||||||
|
// field: topLevelProp:Ljava/lang/String;
|
||||||
|
// getter: getTopLevelProp()Ljava/lang/String;
|
||||||
|
// setter: setTopLevelProp(Ljava/lang/String;)V
|
||||||
|
public final var topLevelProp: kotlin/String?
|
||||||
|
public final get
|
||||||
|
private final /* non-default */ set(<set-?>: kotlin/String?)
|
||||||
|
|
||||||
|
public typealias F<T#0 /* T */, T#1 /* U */> = kotlin/collections/Map<T#0, kotlin/Function1<kotlin/text/StringBuilder^, T#1?>> /* = kotlin/collections/Map<T#0, kotlin/Function1<java/lang/StringBuilder /* = kotlin/text/StringBuilder^ */, T#1?>> */
|
||||||
|
|
||||||
|
public typealias G<T#0 /* S */> = F^<kotlin/collections/List<T#0>, kotlin/collections/Set<T#0>> /* = kotlin/collections/Map<kotlin/collections/List<T#0>, kotlin/Function1<java/lang/StringBuilder /* = kotlin/text/StringBuilder^ */, kotlin/collections/Set<T#0>?>> */
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
fun f(a: AnnotationTarget): String? {
|
||||||
|
return when (a) {
|
||||||
|
AnnotationTarget.FUNCTION -> "1"
|
||||||
|
AnnotationTarget.PROPERTY -> "2"
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
// SyntheticClassKt.class
|
||||||
|
// ------------------------------------------
|
||||||
|
package {
|
||||||
|
|
||||||
|
// signature: f(Lkotlin/annotation/AnnotationTarget;)Ljava/lang/String;
|
||||||
|
public final fun f(a: kotlin/annotation/AnnotationTarget): kotlin/String?
|
||||||
|
}
|
||||||
|
// SyntheticClassKt$WhenMappings.class
|
||||||
|
// ------------------------------------------
|
||||||
|
synthetic class
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
class A<T> {
|
||||||
|
fun <T> a(t: T) {}
|
||||||
|
|
||||||
|
inner class B<U, V : U> {
|
||||||
|
fun <T, U> b(t: T, u: U, v: V) where T : Comparable<T>, T : Cloneable {}
|
||||||
|
|
||||||
|
fun bb(t: T) {}
|
||||||
|
|
||||||
|
inner class C<T, U> {
|
||||||
|
fun <T, U> c(t: T?, u: U?) {}
|
||||||
|
|
||||||
|
fun cc(t: T?, u: U?) {}
|
||||||
|
|
||||||
|
fun z(c: A<Int>.B<Any, Byte>.C<Unit, Long>) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
// A.class
|
||||||
|
// ------------------------------------------
|
||||||
|
public final class A<T#0 /* T */> : kotlin/Any {
|
||||||
|
|
||||||
|
// signature: <init>()V
|
||||||
|
public /* primary */ constructor()
|
||||||
|
|
||||||
|
// signature: a(Ljava/lang/Object;)V
|
||||||
|
public final fun <T#1 /* T */> a(t: T#1): kotlin/Unit
|
||||||
|
|
||||||
|
// nested class: B
|
||||||
|
}
|
||||||
|
// A$B.class
|
||||||
|
// ------------------------------------------
|
||||||
|
public final inner class A.B<T#1 /* U */, T#2 /* V */ : T#1> : kotlin/Any {
|
||||||
|
|
||||||
|
// signature: <init>(LA;)V
|
||||||
|
public /* primary */ constructor()
|
||||||
|
|
||||||
|
// signature: b(Ljava/lang/Comparable;Ljava/lang/Object;Ljava/lang/Object;)V
|
||||||
|
public final fun <T#3 /* T */ : kotlin/Comparable<T#3> & kotlin/Cloneable, T#4 /* U */> b(t: T#3, u: T#4, v: T#2): kotlin/Unit
|
||||||
|
|
||||||
|
// signature: bb(Ljava/lang/Object;)V
|
||||||
|
public final fun bb(t: T#0): kotlin/Unit
|
||||||
|
|
||||||
|
// nested class: C
|
||||||
|
}
|
||||||
|
// A$B$C.class
|
||||||
|
// ------------------------------------------
|
||||||
|
public final inner class A.B.C<T#3 /* T */, T#4 /* U */> : kotlin/Any {
|
||||||
|
|
||||||
|
// signature: <init>(LA$B;)V
|
||||||
|
public /* primary */ constructor()
|
||||||
|
|
||||||
|
// signature: c(Ljava/lang/Object;Ljava/lang/Object;)V
|
||||||
|
public final fun <T#5 /* T */, T#6 /* U */> c(t: T#5?, u: T#6?): kotlin/Unit
|
||||||
|
|
||||||
|
// signature: cc(Ljava/lang/Object;Ljava/lang/Object;)V
|
||||||
|
public final fun cc(t: T#3?, u: T#4?): kotlin/Unit
|
||||||
|
|
||||||
|
// signature: z(LA$B$C;)V
|
||||||
|
public final fun z(c: A<kotlin/Int>.B<kotlin/Any, kotlin/Byte>.C<kotlin/Unit, kotlin/Long>): kotlin/Unit
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||||
|
package test
|
||||||
|
|
||||||
|
import kotlin.internal.RequireKotlin
|
||||||
|
import kotlin.internal.RequireKotlinVersionKind
|
||||||
|
|
||||||
|
@RequireKotlin("1.2", "Klass must not be used!", DeprecationLevel.WARNING, RequireKotlinVersionKind.API_VERSION)
|
||||||
|
class Klass
|
||||||
|
|
||||||
|
class Konstructor @RequireKotlin("42.0", "Konstructor must not be used!", DeprecationLevel.WARNING, RequireKotlinVersionKind.LANGUAGE_VERSION, 42) constructor()
|
||||||
|
|
||||||
|
@RequireKotlin("1.1", level = DeprecationLevel.HIDDEN, versionKind = RequireKotlinVersionKind.API_VERSION, errorCode = 314)
|
||||||
|
typealias Typealias = String
|
||||||
|
|
||||||
|
@RequireKotlin("1.2.40", level = DeprecationLevel.ERROR, versionKind = RequireKotlinVersionKind.COMPILER_VERSION)
|
||||||
|
fun function() {}
|
||||||
|
|
||||||
|
@RequireKotlin("1.3", "property must not be used!")
|
||||||
|
val property = ""
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
// test/Klass.class
|
||||||
|
// ------------------------------------------
|
||||||
|
// requires API version 1.2.0 (level=WARNING, message="Klass must not be used!")
|
||||||
|
public final class test/Klass : kotlin/Any {
|
||||||
|
|
||||||
|
// signature: <init>()V
|
||||||
|
public /* primary */ constructor()
|
||||||
|
}
|
||||||
|
// test/Konstructor.class
|
||||||
|
// ------------------------------------------
|
||||||
|
public final class test/Konstructor : kotlin/Any {
|
||||||
|
|
||||||
|
// requires language version 42.0.0 (level=WARNING, errorCode=42, message="Konstructor must not be used!")
|
||||||
|
// signature: <init>()V
|
||||||
|
public /* primary */ constructor()
|
||||||
|
}
|
||||||
|
// test/VersionRequirementKt.class
|
||||||
|
// ------------------------------------------
|
||||||
|
package {
|
||||||
|
|
||||||
|
// requires compiler version 1.2.40 (level=ERROR)
|
||||||
|
// signature: function()V
|
||||||
|
public final fun function(): kotlin/Unit
|
||||||
|
|
||||||
|
// requires language version 1.3.0 (level=ERROR, message="property must not be used!")
|
||||||
|
// field: property:Ljava/lang/String;
|
||||||
|
// getter: getProperty()Ljava/lang/String;
|
||||||
|
// synthetic method for annotations: property$annotations()V
|
||||||
|
public final val property: kotlin/String /* = ... */
|
||||||
|
public final get
|
||||||
|
|
||||||
|
// requires API version 1.1.0 (level=HIDDEN, errorCode=314)
|
||||||
|
public typealias Typealias = kotlin/String /* = kotlin/String */
|
||||||
|
}
|
||||||
@@ -134,6 +134,7 @@ include ":kotlin-build-common",
|
|||||||
":tools:binary-compatibility-validator",
|
":tools:binary-compatibility-validator",
|
||||||
":tools:kotlin-stdlib-js-merger",
|
":tools:kotlin-stdlib-js-merger",
|
||||||
":tools:kotlin-stdlib-gen",
|
":tools:kotlin-stdlib-gen",
|
||||||
|
":tools:kotlinp",
|
||||||
":kotlin-gradle-plugin-api",
|
":kotlin-gradle-plugin-api",
|
||||||
":kotlin-gradle-plugin",
|
":kotlin-gradle-plugin",
|
||||||
":kotlin-gradle-plugin-test-utils-embeddable",
|
":kotlin-gradle-plugin-test-utils-embeddable",
|
||||||
@@ -240,6 +241,7 @@ project(':kotlin-source-sections-compiler-plugin').projectDir = "$rootDir/plugin
|
|||||||
project(':tools:binary-compatibility-validator').projectDir = "$rootDir/libraries/tools/binary-compatibility-validator" as File
|
project(':tools:binary-compatibility-validator').projectDir = "$rootDir/libraries/tools/binary-compatibility-validator" as File
|
||||||
project(':tools:kotlin-stdlib-js-merger').projectDir = "$rootDir/libraries/tools/kotlin-stdlib-js-merger" as File
|
project(':tools:kotlin-stdlib-js-merger').projectDir = "$rootDir/libraries/tools/kotlin-stdlib-js-merger" as File
|
||||||
project(':tools:kotlin-stdlib-gen').projectDir = "$rootDir/libraries/tools/kotlin-stdlib-gen" as File
|
project(':tools:kotlin-stdlib-gen').projectDir = "$rootDir/libraries/tools/kotlin-stdlib-gen" as File
|
||||||
|
project(':tools:kotlinp').projectDir = "$rootDir/libraries/tools/kotlinp" as File
|
||||||
project(':kotlin-gradle-plugin-api').projectDir = "$rootDir/libraries/tools/kotlin-gradle-plugin-api" as File
|
project(':kotlin-gradle-plugin-api').projectDir = "$rootDir/libraries/tools/kotlin-gradle-plugin-api" as File
|
||||||
project(':kotlin-gradle-plugin').projectDir = "$rootDir/libraries/tools/kotlin-gradle-plugin" as File
|
project(':kotlin-gradle-plugin').projectDir = "$rootDir/libraries/tools/kotlin-gradle-plugin" as File
|
||||||
project(':kotlin-gradle-plugin-test-utils-embeddable').projectDir = "$rootDir/libraries/tools/kotlin-gradle-plugin-test-utils-embeddable" as File
|
project(':kotlin-gradle-plugin-test-utils-embeddable').projectDir = "$rootDir/libraries/tools/kotlin-gradle-plugin-test-utils-embeddable" as File
|
||||||
|
|||||||
Reference in New Issue
Block a user