Add basic support for class references

Also use class name for `Any.toString` and `Throwable.toString`.
This commit is contained in:
SvyatoslavScherbina
2017-09-26 10:59:45 +03:00
committed by GitHub
parent a6ca64871f
commit 786374ef86
21 changed files with 573 additions and 41 deletions
@@ -44,8 +44,8 @@ internal class KonanLower(val context: Context) {
irModule.files.forEach(TestProcessor(context)::lower)
}
phaser.phase(KonanPhase.LOWER_SPECIAL_CALLS) {
irModule.files.forEach(SpecialCallsLowering(context)::lower)
phaser.phase(KonanPhase.LOWER_BEFORE_INLINE) {
irModule.files.forEach(PreInlineLowering(context)::lower)
}
phaser.phase(KonanPhase.LOWER_INLINE_CONSTRUCTORS) {
@@ -29,9 +29,9 @@ enum class KonanPhase(val description: String,
/* */ BACKEND("All backend"),
/* ... */ LOWER("IR Lowering"),
/* ... ... */ TEST_PROCESSOR("Unit test processor"),
/* ... ... */ LOWER_SPECIAL_CALLS("Special calls processing before inlining"),
/* ... ... */ LOWER_INLINE_CONSTRUCTORS("Inline constructors transformation", LOWER_SPECIAL_CALLS),
/* ... ... */ LOWER_INLINE("Functions inlining", LOWER_INLINE_CONSTRUCTORS, LOWER_SPECIAL_CALLS),
/* ... ... */ LOWER_BEFORE_INLINE("Special operations processing before inlining"),
/* ... ... */ LOWER_INLINE_CONSTRUCTORS("Inline constructors transformation", LOWER_BEFORE_INLINE),
/* ... ... */ LOWER_INLINE("Functions inlining", LOWER_INLINE_CONSTRUCTORS, LOWER_BEFORE_INLINE),
/* ... ... ... */ DESERIALIZER("Deserialize inline bodies"),
/* ... ... */ LOWER_INTEROP_PART1("Interop lowering, part 1", LOWER_INLINE),
/* ... ... */ LOWER_FOR_LOOPS("For loops lowering"),
@@ -28,10 +28,15 @@ import org.jetbrains.kotlin.builtins.isFunctionType
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.symbols.IrEnumEntrySymbol
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.util.constructors
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.KotlinType
import kotlin.properties.Delegates
@@ -89,6 +94,12 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable): Sym
it to symbolTable.referenceClass(context.getInternalClass("${it.classFqName.shortName()}Box"))
}
val valueClassToBox = ValueType.values().associate {
val valueClassId = ClassId.topLevel(it.classFqName.toSafe())
val valueClassDescriptor = context.builtIns.builtInsModule.findClassAcrossModuleDependencies(valueClassId)!!
valueClassDescriptor to boxClasses[it]!!
}
val unboxFunctions = ValueType.values().mapNotNull {
val unboxFunctionName = "unbox${it.classFqName.shortName()}"
context.getInternalFunctions(unboxFunctionName).atMostOne()?.let { descriptor ->
@@ -170,6 +181,17 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable): Sym
val kLocalDelegatedPropertyImpl = symbolTable.referenceClass(context.reflectionTypes.kLocalDelegatedPropertyImpl)
val kLocalDelegatedMutablePropertyImpl = symbolTable.referenceClass(context.reflectionTypes.kLocalDelegatedMutablePropertyImpl)
val getClassTypeInfo = internalFunction("getClassTypeInfo")
val getObjectTypeInfo = internalFunction("getObjectTypeInfo")
val kClassImpl = internalClass("KClassImpl")
val kClassImplConstructor by lazy { kClassImpl.constructors.single() }
private fun internalFunction(name: String): IrSimpleFunctionSymbol =
symbolTable.referenceSimpleFunction(context.getInternalFunctions(name).single())
private fun internalClass(name: String): IrClassSymbol =
symbolTable.referenceClass(context.getInternalClass(name))
private fun getKonanTestClass(className: String) = symbolTable.referenceClass(
builtInsPackage("konan", "test").getContributedClassifier(
Name.identifier(className), NoLookupLocation.FROM_BACKEND
@@ -216,4 +238,4 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable): Sym
kind.runtimeKindName, NoLookupLocation.FROM_BACKEND
) as ClassDescriptor)
}
}
}
@@ -1386,8 +1386,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
//-------------------------------------------------------------------------//
private fun evaluateStringConst(value: IrConst<String>) =
context.llvm.staticData.kotlinStringLiteral(
context.builtIns.stringType, value).llvm
context.llvm.staticData.kotlinStringLiteral(value.value).llvm
private fun evaluateConst(value: IrConst<*>): LLVMValueRef {
context.log{"evaluateConst : ${ir2string(value)}"}
@@ -2007,6 +2006,22 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
interop.readBits -> genReadBits(args)
interop.writeBits -> genWriteBits(args)
context.ir.symbols.getClassTypeInfo.descriptor -> {
val typeArgument = callee.getTypeArgumentOrDefault(descriptor.typeParameters.single())
val typeArgumentClass = TypeUtils.getClassDescriptor(typeArgument)
if (typeArgumentClass == null) {
// E.g. for `T::class` in a body of an inline function itself.
functionGenerationContext.unreachable()
kNullInt8Ptr
} else {
val classDescriptor = context.ir.symbols.valueClassToBox[typeArgumentClass]?.descriptor
?: typeArgumentClass
val typeInfo = codegen.typeInfoValue(classDescriptor)
LLVMConstBitCast(typeInfo, kInt8Ptr)!!
}
}
else -> TODO(callee.descriptor.original.toString())
}
}
@@ -23,9 +23,11 @@ import org.jetbrains.kotlin.backend.konan.isExternalObjCClassMethod
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.constants.StringValue
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf
internal class RTTIGenerator(override val context: Context) : ContextUtils {
@@ -45,7 +47,9 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
val methods: ConstValue,
val methodsCount: Int,
val fields: ConstValue,
val fieldsCount: Int) :
val fieldsCount: Int,
val packageName: String?,
val relativeName: String?) :
Struct(
runtime.typeInfoType,
@@ -64,9 +68,18 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
Int32(methodsCount),
fields,
Int32(fieldsCount)
Int32(fieldsCount),
kotlinStringLiteral(packageName),
kotlinStringLiteral(relativeName)
)
private fun kotlinStringLiteral(string: String?): ConstPointer = if (string == null) {
NullPointer(runtime.objHeaderType)
} else {
staticData.kotlinStringLiteral(string)
}
private fun exportTypeInfoIfRequired(classDesc: ClassDescriptor, typeInfoGlobal: LLVMValueRef?) {
val annot = classDesc.annotations.findAnnotation(FqName("konan.ExportTypeInfo"))
if (annot != null) {
@@ -159,12 +172,17 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
val methodsPtr = staticData.placeGlobalConstArray("kmethods:$className",
runtime.methodTableRecordType, methods)
val reflectionInfo = getReflectionInfo(classDesc)
val typeInfo = TypeInfo(name, size,
superType,
objOffsetsPtr, objOffsets.size,
interfacesPtr, interfaces.size,
methodsPtr, methods.size,
fieldsPtr, if (classDesc.isInterface) -1 else fields.size)
fieldsPtr, if (classDesc.isInterface) -1 else fields.size,
reflectionInfo.packageName,
reflectionInfo.relativeName
)
val typeInfoGlobal = llvmDeclarations.typeInfoGlobal
@@ -201,4 +219,26 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
}
return context.specialDeclarationsFactory.getBridgeDescriptor(OverriddenFunctionDescriptor(bridgeOwner, overriddenDescriptor))
}
data class ReflectionInfo(val packageName: String?, val relativeName: String?)
private fun getReflectionInfo(descriptor: ClassDescriptor): ReflectionInfo {
// Use data from value class in type info for box class:
val descriptorForReflection = context.ir.symbols.valueClassToBox.entries
.firstOrNull { it.value.descriptor == descriptor }
?.key ?: descriptor
return if (DescriptorUtils.isAnonymousObject(descriptorForReflection)) {
ReflectionInfo(packageName = null, relativeName = null)
} else if (DescriptorUtils.isLocal(descriptorForReflection)) {
ReflectionInfo(packageName = null, relativeName = descriptorForReflection.name.asString())
} else {
ReflectionInfo(
packageName = descriptorForReflection.findPackage().fqName.asString(),
relativeName = descriptorForReflection.parentsWithSelf
.takeWhile { it is ClassDescriptor }.toList().reversed()
.joinToString(".") { it.name.asString() }
)
}
}
}
@@ -157,8 +157,8 @@ internal class StaticData(override val context: Context): ContextUtils {
fun cStringLiteral(value: String) =
cStringLiterals.getOrPut(value) { placeCStringLiteral(value) }
fun kotlinStringLiteral(type: KotlinType, value: IrConst<String>) =
stringLiterals.getOrPut(value.value) { createKotlinStringLiteral(type, value) }
fun kotlinStringLiteral(value: String) =
stringLiterals.getOrPut(value) { createKotlinStringLiteral(value) }
}
/**
@@ -42,8 +42,9 @@ private fun StaticData.arrayHeader(typeInfo: ConstPointer, length: Int): Struct
return Struct(runtime.arrayHeaderType, typeInfo, Int32(containerOffsetNegative), Int32(length))
}
internal fun StaticData.createKotlinStringLiteral(type: KotlinType, irConst: IrConst<String>): ConstPointer {
val value = irConst.value
internal fun StaticData.createKotlinStringLiteral(value: String): ConstPointer {
val type = context.builtIns.stringType
val name = "kstr:" + value.globalHashBase64
val elements = value.toCharArray().map(::Char16)
@@ -1,33 +1,58 @@
package org.jetbrains.kotlin.backend.konan.lower
import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.lower.IrBuildingTransformer
import org.jetbrains.kotlin.backend.common.lower.at
import org.jetbrains.kotlin.backend.konan.*
import org.jetbrains.kotlin.backend.konan.KonanConfigKeys
import org.jetbrains.kotlin.ir.builders.irCall
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrConst
import org.jetbrains.kotlin.ir.expressions.IrConstKind
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrSpreadElement
import org.jetbrains.kotlin.ir.expressions.IrVararg
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.types.typeUtil.isUnit
/**
* This pass runs before inlining and performs the following additional transformations over some calls:
* This pass runs before inlining and performs the following additional transformations over some operations:
* - Assertion call removal.
* - Convert immutableBinaryBlobOf() arguments to special IrConst.
* - Convert `obj::class` and `Class::class` to calls.
*/
internal class SpecialCallsLowering(val context: Context) : FileLoweringPass {
internal class PreInlineLowering(val context: Context) : FileLoweringPass {
private val asserts = context.ir.symbols.asserts
private val symbols get() = context.ir.symbols
private val asserts = symbols.asserts
private val enableAssertions = context.config.configuration.getBoolean(KonanConfigKeys.ENABLE_ASSERTIONS)
override fun lower(irFile: IrFile) {
irFile.transformChildrenVoid(object : IrElementTransformerVoid() {
irFile.transformChildrenVoid(object : IrBuildingTransformer(context) {
override fun visitClassReference(expression: IrClassReference): IrExpression {
expression.transformChildrenVoid()
builder.at(expression)
val typeArgument = expression.descriptor.defaultType
return builder.irCall(symbols.kClassImplConstructor, listOf(typeArgument)).apply {
putValueArgument(0, builder.irCall(symbols.getClassTypeInfo, listOf(typeArgument)))
}
}
override fun visitGetClass(expression: IrGetClass): IrExpression {
expression.transformChildrenVoid()
builder.at(expression)
val typeArgument = expression.type.arguments.single().type
return builder.irCall(symbols.kClassImplConstructor, listOf(typeArgument)).apply {
val typeInfo = builder.irCall(symbols.getObjectTypeInfo).apply {
putValueArgument(0, expression.argument)
}
putValueArgument(0, typeInfo)
}
}
override fun visitCall(expression: IrCall): IrExpression {
expression.transformChildrenVoid(this)
+9
View File
@@ -928,6 +928,15 @@ task lateinit_inBaseClass(type: RunKonanTest) {
source = "codegen/lateinit/inBaseClass.kt"
}
task kclass0(type: RunKonanTest) {
source = "codegen/kclass/kclass0.kt"
}
task kclass1(type: RunKonanTest) {
goldValue = "OK :D\n"
source = "codegen/kclass/kclass1.kt"
}
task coroutines_simple(type: RunKonanTest) {
disabled = (project.testTarget == 'wasm32') // llvm: 'WebAssembly hasn't implemented computed gotos'
goldValue = "42\n"
@@ -0,0 +1,76 @@
import kotlin.reflect.KClass
fun main(args: Array<String>) {
checkClass(Any::class, "kotlin.Any", "Any", Any(), null)
checkClass(Int::class, "kotlin.Int", "Int", 42, "17")
checkClass(String::class, "kotlin.String", "String", "17", 42)
checkClass(RootClass::class, "RootClass", "RootClass", RootClass(), Any())
checkClass(RootClass.Nested::class, "RootClass.Nested", "Nested", RootClass.Nested(), Any())
class Local {
val captured = args
inner class Inner
}
checkClass(Local::class, null, "Local", Local(), Any())
checkClass(Local.Inner::class, null, "Inner", Local().Inner(), Any())
val obj = object : Any() {
val captured = args
inner class Inner
val innerKClass = Inner::class
}
checkClass(obj::class, null, null, obj, Any())
checkClass(obj.innerKClass, null, "Inner", obj.Inner(), Any())
// Interfaces:
checkClass(Comparable::class, "kotlin.Comparable", "Comparable", 42, Any())
checkClass(Interface::class, "Interface", "Interface", object : Interface {}, Any())
checkInstanceClass(Any(), Any::class)
checkInstanceClass(42, Int::class)
assert(42::class == Int::class)
checkReifiedClass<Int>(Int::class)
checkReifiedClass<Int?>(Int::class)
checkReifiedClass2<Int>(Int::class)
checkReifiedClass2<Int?>(Int::class)
checkReifiedClass<Any>(Any::class)
checkReifiedClass2<Any>(Any::class)
checkReifiedClass2<Any?>(Any::class)
checkReifiedClass<Local>(Local::class)
checkReifiedClass2<Local>(Local::class)
checkReifiedClass<RootClass>(RootClass::class)
checkReifiedClass2<RootClass>(RootClass::class)
}
class RootClass {
class Nested
}
interface Interface
fun checkClass(
clazz: KClass<*>,
expectedQualifiedName: String?, expectedSimpleName: String?,
expectedInstance: Any, expectedNotInstance: Any?
) {
assert(clazz.qualifiedName == expectedQualifiedName)
assert(clazz.simpleName == expectedSimpleName)
assert(clazz.isInstance(expectedInstance))
if (expectedNotInstance != null) assert(!clazz.isInstance(expectedNotInstance))
}
fun checkInstanceClass(instance: Any, clazz: KClass<*>) {
assert(instance::class == clazz)
}
inline fun <reified T> checkReifiedClass(expectedClass: KClass<*>) {
assert(T::class == expectedClass)
}
inline fun <reified T> checkReifiedClass2(expectedClass: KClass<*>) {
checkReifiedClass<T>(expectedClass)
checkReifiedClass<T?>(expectedClass)
}
@@ -0,0 +1,53 @@
// FILE: main.kt
fun main(args: Array<String>) {
com.github.salomonbrys.kmffkn.App(testQualified = true)
}
// FILE: app.kt
// Taken from:
// https://github.com/SalomonBrys/kmffkn/blob/master/shared/main/kotlin/com/github/salomonbrys/kmffkn/app.kt
package com.github.salomonbrys.kmffkn
@DslMarker
annotation class MyDsl
@MyDsl
class DslMain {
fun <T: Any> kClass(block: KClassDsl.() -> T): T = KClassDsl().block()
}
@MyDsl
class KClassDsl {
inline fun <reified T: Any> of() = T::class
}
fun <T: Any> dsl(block: DslMain.() -> T): T = DslMain().block()
class Test
class App(testQualified: Boolean) {
@Volatile // This could be noop in Kotlin Native, or the equivalent of volatile in C.
var type = dsl {
kClass {
//kClass { } // This should error if uncommented because of `@DslMarker`.
of<Test>()
}
}
init {
assert(type.simpleName == "Test")
if (testQualified)
assert(type.qualifiedName == "com.github.salomonbrys.kmffkn.Test") // This is not really necessary, but always better :).
assert(String::class == String::class)
assert(String::class != Int::class)
assert(Test()::class == Test()::class)
assert(Test()::class == Test::class)
println("OK :D")
}
}
+4
View File
@@ -70,4 +70,8 @@ void Kotlin_system_exitProcess(KInt status) {
konan::exit(status);
}
const void* Kotlin_Any_getTypeInfo(KConstRef obj) {
return obj->type_info();
}
} // extern "C"
-12
View File
@@ -68,18 +68,6 @@ template <typename T> OBJ_GETTER(Kotlin_toStringRadix, T value, KInt radix) {
extern "C" {
OBJ_GETTER(Kotlin_Any_toString, KConstRef thiz) {
char cstring[80];
if (IsArray(thiz)) {
konan::snprintf(cstring, sizeof(cstring), "%d@%p: array of %d",
Kotlin_Any_hashCode(thiz), thiz->type_info_, thiz->array()->count_);
} else {
konan::snprintf(cstring, sizeof(cstring), "%d@%p: object",
Kotlin_Any_hashCode(thiz), thiz->type_info_);
}
RETURN_RESULT_OF(CreateStringFromCString, cstring);
}
OBJ_GETTER(Kotlin_Byte_toString, KByte value) {
char cstring[8];
konan::snprintf(cstring, sizeof(cstring), "%d", value);
+11
View File
@@ -22,6 +22,8 @@
#include "Common.h"
#include "Names.h"
struct ObjHeader;
// An element of sorted by hash in-place array representing methods.
// For systems where introspection is not needed - only open methods are in
// this table.
@@ -56,6 +58,15 @@ struct TypeInfo {
// Is negative to mark an interface.
int32_t fieldsCount_;
// String for the fully qualified dot-separated name of the package containing class,
// or `null` if the class is local or anonymous.
ObjHeader* packageName_;
// String for the qualified class name relative to the containing package
// (e.g. TopLevel.Nested1.Nested2), or simple class name if it is local,
// or `null` if the class is anonymous.
ObjHeader* relativeName_;
// vtable starts just after declared contents of the TypeInfo:
// void* const vtable_[];
};
+12
View File
@@ -50,4 +50,16 @@ void CheckInstance(const ObjHeader* obj, const TypeInfo* type_info) {
ThrowClassCastException();
}
KBoolean Kotlin_TypeInfo_isInstance(KConstRef obj, KNativePtr typeInfo) {
return IsInstance(obj, reinterpret_cast<const TypeInfo*>(typeInfo));
}
OBJ_GETTER(Kotlin_TypeInfo_getPackageName, KNativePtr typeInfo) {
RETURN_OBJ(reinterpret_cast<const TypeInfo*>(typeInfo)->packageName_);
}
OBJ_GETTER(Kotlin_TypeInfo_getRelativeName, KNativePtr typeInfo) {
RETURN_OBJ(reinterpret_cast<const TypeInfo*>(typeInfo)->relativeName_);
}
} // extern "C"
@@ -0,0 +1,67 @@
/*
* Copyright 2010-2017 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 konan.internal
import kotlin.reflect.KClass
@ExportForCompiler
internal class KClassImpl<T : Any>(private val typeInfo: NativePtr) : KClass<T> {
override val simpleName: String?
get() {
val relativeName = getRelativeName(typeInfo)
?: return null
return relativeName.substringAfterLast(".")
}
override val qualifiedName: String?
get() {
val packageName = getPackageName(typeInfo)
?: return null
val relativeName = getRelativeName(typeInfo)!!
return if (packageName.isEmpty()) {
relativeName
} else {
"$packageName.$relativeName"
}
}
override fun isInstance(value: Any?): Boolean = value != null && isInstance(value, this.typeInfo)
override fun equals(other: Any?): Boolean =
other is KClassImpl<*> && this.typeInfo == other.typeInfo
override fun hashCode(): Int = typeInfo.hashCode()
}
@ExportForCompiler
@SymbolName("Kotlin_Any_getTypeInfo")
internal external fun getObjectTypeInfo(obj: Any): NativePtr
@ExportForCompiler
@Intrinsic
internal external inline fun <reified T : Any> getClassTypeInfo(): NativePtr
@SymbolName("Kotlin_TypeInfo_getPackageName")
private external fun getPackageName(typeInfo: NativePtr): String?
@SymbolName("Kotlin_TypeInfo_getRelativeName")
private external fun getRelativeName(typeInfo: NativePtr): String?
@SymbolName("Kotlin_TypeInfo_isInstance")
private external fun isInstance(obj: Any, typeInfo: NativePtr): Boolean
+7 -2
View File
@@ -48,8 +48,13 @@ public open class Any {
/**
* Returns a string representation of the object.
*/
@SymbolName("Kotlin_Any_toString")
external public open fun toString(): String
public open fun toString(): String {
val kClass = this::class
val className = kClass.qualifiedName ?: kClass.simpleName ?: "<object>"
val unsignedHashCode = this.hashCode().toLong() and 0xffffffffL
val hashCodeStr = unsignedHashCode.toString(16)
return "$className@$hashCodeStr"
}
}
public fun Any?.hashCode() = if (this != null) this.hashCode() else 0
+2 -1
View File
@@ -50,7 +50,8 @@ public open class Throwable(open val message: String?, open val cause: Throwable
}
override fun toString(): String {
val s = "Throwable" // TODO: should be class name
val kClass = this::class
val s = kClass.qualifiedName ?: kClass.simpleName ?: "Throwable"
return if (message != null) s + ": " + message.toString() else s
}
}
@@ -0,0 +1,149 @@
/*
* Copyright 2010-2017 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 kotlin.reflect
/**
* Represents a class and provides introspection capabilities.
* Instances of this class are obtainable by the `::class` syntax.
* See the [Kotlin language documentation](http://kotlinlang.org/docs/reference/reflection.html#class-references)
* for more information.
*
* @param T the type of the class.
*/
public interface KClass<T : Any> : KDeclarationContainer, KAnnotatedElement, KClassifier {
/**
* The simple name of the class as it was declared in the source code,
* or `null` if the class has no name (if, for example, it is an anonymous object literal).
*/
public val simpleName: String?
/**
* The fully qualified dot-separated name of the class,
* or `null` if the class is local or it is an anonymous object literal.
*/
public val qualifiedName: String?
// /**
// * All functions and properties accessible in this class, including those declared in this class
// * and all of its superclasses. Does not include constructors.
// */
// override val members: Collection<KCallable<*>>
//
// /**
// * All constructors declared in this class.
// */
// public val constructors: Collection<KFunction<T>>
//
// /**
// * All classes declared inside this class. This includes both inner and static nested classes.
// */
// public val nestedClasses: Collection<KClass<*>>
//
// /**
// * The instance of the object declaration, or `null` if this class is not an object declaration.
// */
// public val objectInstance: T?
/**
* Returns `true` if [value] is an instance of this class on a given platform.
*/
@SinceKotlin("1.1")
public fun isInstance(value: Any?): Boolean
// /**
// * The list of type parameters of this class. This list does *not* include type parameters of outer classes.
// */
// @SinceKotlin("1.1")
// public val typeParameters: List<KTypeParameter>
//
// /**
// * The list of immediate supertypes of this class, in the order they are listed in the source code.
// */
// @SinceKotlin("1.1")
// public val supertypes: List<KType>
//
// /**
// * Visibility of this class, or `null` if its visibility cannot be represented in Kotlin.
// */
// @SinceKotlin("1.1")
// public val visibility: KVisibility?
//
// /**
// * `true` if this class is `final`.
// */
// @SinceKotlin("1.1")
// public val isFinal: Boolean
//
// /**
// * `true` if this class is `open`.
// */
// @SinceKotlin("1.1")
// public val isOpen: Boolean
//
// /**
// * `true` if this class is `abstract`.
// */
// @SinceKotlin("1.1")
// public val isAbstract: Boolean
//
// /**
// * `true` if this class is `sealed`.
// * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/classes.html#sealed-classes)
// * for more information.
// */
// @SinceKotlin("1.1")
// public val isSealed: Boolean
//
// /**
// * `true` if this class is a data class.
// * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/data-classes.html)
// * for more information.
// */
// @SinceKotlin("1.1")
// public val isData: Boolean
//
// /**
// * `true` if this class is an inner class.
// * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/nested-classes.html#inner-classes)
// * for more information.
// */
// @SinceKotlin("1.1")
// public val isInner: Boolean
//
// /**
// * `true` if this class is a companion object.
// * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/object-declarations.html#companion-objects)
// * for more information.
// */
// @SinceKotlin("1.1")
// public val isCompanion: Boolean
/**
* Returns `true` if this [KClass] instance represents the same Kotlin class as the class represented by [other].
* On JVM this means that all of the following conditions are satisfied:
*
* 1. [other] has the same (fully qualified) Kotlin class name as this instance.
* 2. [other]'s backing [Class] object is loaded with the same class loader as the [Class] object of this instance.
* 3. If the classes represent [Array], then [Class] objects of their element types are equal.
*
* For example, on JVM, [KClass] instances for a primitive type (`int`) and the corresponding wrapper type (`java.lang.Integer`)
* are considered equal, because they have the same fully qualified name "kotlin.Int".
*/
override fun equals(other: Any?): Boolean
override fun hashCode(): Int
}
@@ -0,0 +1,26 @@
/*
* Copyright 2010-2017 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 kotlin.reflect
/**
* A classifier is either a class or a type parameter.
*
* @see [KClass]
* @see [KTypeParameter]
*/
@SinceKotlin("1.1")
public interface KClassifier
@@ -0,0 +1,28 @@
/*
* Copyright 2010-2017 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 kotlin.reflect
/**
* Represents an entity which may contain declarations of any other entities,
* such as a class or a package.
*/
public interface KDeclarationContainer {
// /**
// * All functions and properties accessible in this container.
// */
// public val members: Collection<KCallable<*>>
}